// 解忧 前端应用
class RelieveAnxietyApp {
    constructor() {
        this.currentCharacter = null;
        this.currentSession = null;
        this.selectedSkill = null;
        this.isRecording = false;
        this.mediaRecorder = null;
        this.audioChunks = [];
        this.currentUser = null;
        this.token = localStorage.getItem('token');
        this.currentAudio = null; // 当前播放的音频对象
        this.isPlaying = false; // 是否正在播放
        this.allCharacters = []; // 存储所有角色数据
        this.displayedCharacters = []; // 当前显示的角色
        this.displayCount = 6; // 每次显示的角色数量（下方网格）
        this.featuredCount = 3; // 每次显示的精选角色数量（上方卡片）
        this.isAllCharactersVisible = false; // 是否显示全部人物卡片
        this.availableModels = []; // 可用模型列表
        this.currentModel = 'GLM-4'; // 当前模型
        
        // 语音识别策略相关
        this.availableStrategies = {};
        this.selectedStrategy = localStorage.getItem('selectedAsrStrategy') || '';
        
        // 语音通话相关状态
        this.isVoiceCallActive = false;
        this.voiceCallStream = null;
        this.voiceCallRecorder = null;
        this.isMicrophoneMuted = false;
        this.isTextDisplayMinimized = false;
        this.currentAiResponse = '';
        this.voiceCallModal = null;
        this.isAiSpeaking = false;
        this.currentAudio = null;
        this.isProcessingVoiceInput = false;
        this.voiceCallTimeouts = []; // 存储所有语音通话相关的定时器
        
        // 搜索历史相关
        this.searchHistory = JSON.parse(localStorage.getItem('searchHistory') || '[]');
        this.maxSearchHistory = 10; // 最多保存10条搜索记录
        
        // 侧边栏数据缓存
        this.sidebarCache = {
            characters: {
                data: null,
                timestamp: null,
                ttl: 30 * 60 * 1000 // 30分钟缓存时间
            },
            chatHistory: {
                data: null,
                timestamp: null,
                ttl: 10 * 60 * 1000 // 10分钟缓存时间
            },
            searchHistory: {
                data: null,
                timestamp: null,
                ttl: 60 * 60 * 1000 // 1小时缓存时间
            }
        };
        
        // 缓存键名
        this.cacheKeys = {
            characters: 'sidebar_characters_cache',
            chatHistory: 'sidebar_chat_history_cache',
            searchHistory: 'sidebar_search_history_cache'
        };
        
        // 侧边栏分页相关
        this.itemsPerPage = 5; // 每页显示5个
        this.sectionStates = {
            searchHistory: { expanded: false, currentPage: 1 },
            allCharacters: { expanded: false, currentPage: 1 },
            chatHistory: { expanded: false, currentPage: 1 }
        };
        
        this.init();
        this.loadCachedData();
    }
    
    async init() {
        await this.checkLoginStatus();
        await this.loadCharacters();
        await this.loadAvailableModels();
        await this.getCurrentModel();
        await this.loadVoiceRecognitionStrategies();
        this.setupEventListeners();
        this.setupAuthListeners();
        this.setupSearchListeners();
        
        // 预加载侧边栏数据
        this.preloadSidebarData();
    }
    
    async loadCharacters() {
        try {
            const response = await fetch('/api/characters');
            if (response.ok) {
                const characters = await response.json();
                this.allCharacters = characters;
                this.refreshFeaturedCharacters();
                
                // 缓存角色数据
                this.setCacheData('characters', characters);
                
                console.log(`成功加载 ${characters.length} 个角色到本地缓存`);
                // 不再自动加载全部人物卡片，只在需要时加载
            } else {
                console.error('加载角色失败:', response.status);
                this.allCharacters = []; // 确保数组为空，触发后端搜索
            }
        } catch (error) {
            console.error('网络错误:', error);
            this.allCharacters = []; // 确保数组为空，触发后端搜索
        }
    }
    
    renderCharacters(characters) {
        const container = document.getElementById('characterList');
        container.innerHTML = '';
        
        characters.forEach(character => {
            const characterCard = this.createCharacterCard(character);
            container.appendChild(characterCard);
        });
    }

    refreshFeaturedCharacters() {
        if (this.allCharacters.length === 0) return;
        
        const stackContainer = document.getElementById('threeCardStack');
        if (!stackContainer) {
            // 如果没有堆叠容器，使用普通刷新
            const shuffled = [...this.allCharacters].sort(() => 0.5 - Math.random());
            const featuredCharacters = shuffled.slice(0, this.featuredCount);
            this.renderFeaturedCharacters(featuredCharacters);
            return;
        }
        
        // 添加Card Beam聚合动画类
        stackContainer.classList.add('refreshing');
        
        // 等待聚合动画完成后更新内容
        setTimeout(() => {
            // 随机选择要显示的精选角色
            const shuffled = [...this.allCharacters].sort(() => 0.5 - Math.random());
            const featuredCharacters = shuffled.slice(0, this.featuredCount);
            
            // 重新构建Card Beam结构
            stackContainer.innerHTML = '';
            
            // 添加光束背景
            const beamBg = document.createElement('div');
            beamBg.className = 'card-beam-bg';
            stackContainer.appendChild(beamBg);
            
            // 创建卡片束容器
            const cardBeamStack = document.createElement('div');
            cardBeamStack.className = 'card-beam-stack';
            
            featuredCharacters.forEach((character, index) => {
                const characterCard = this.createStackCharacterCard(character, index);
                cardBeamStack.appendChild(characterCard);
            });
            
            stackContainer.appendChild(cardBeamStack);
            
            // 重新设置交互效果
            this.setupCardBeamInteractions();
            
            // 移除聚合动画类，添加散开动画类
            stackContainer.classList.remove('refreshing');
            stackContainer.classList.add('refreshing-scatter');
            
            // 散开动画完成后清理类名
            setTimeout(() => {
                stackContainer.classList.remove('refreshing-scatter');
            }, 1000);
            
            this.showToast('已更新精选角色', 'success');
        }, 500); // Card Beam聚合动画时间的一半
    }
    
    /**
     * 设置Card Beam交互效果
     */
    setupCardBeamInteractions() {
        const stackContainer = document.getElementById('threeCardStack');
        if (!stackContainer) return;
        
        const cards = stackContainer.querySelectorAll('.stack-card');
        const beamBg = stackContainer.querySelector('.card-beam-bg');
        
        cards.forEach((card, index) => {
            // 悬停效果
            card.addEventListener('mouseenter', () => {
                // 增强光束效果
                if (beamBg) {
                    beamBg.style.opacity = '1';
                    beamBg.style.transform = 'translate(-50%, -50%) rotate(5deg) scaleX(1.5)';
                }
                
                // 添加光束聚焦效果
                card.style.filter = 'brightness(1.1) saturate(1.2)';
            });
            
            card.addEventListener('mouseleave', () => {
                // 恢复光束效果
                if (beamBg) {
                    beamBg.style.opacity = '0.8';
                    beamBg.style.transform = 'translate(-50%, -50%) rotate(0deg) scaleX(1)';
                }
                
                // 恢复卡片效果
                card.style.filter = 'brightness(1) saturate(1)';
            });
            
            // 点击效果
            card.addEventListener('click', () => {
                // 添加点击光束爆发效果
                this.createBeamBurst(card);
            });
        });
    }
    
    /**
     * 创建光束爆发效果
     */
    createBeamBurst(card) {
        const burst = document.createElement('div');
        burst.style.cssText = `
            position: absolute;
            top: 50%;
            left: 50%;
            width: 2px;
            height: 2px;
            background: linear-gradient(45deg, var(--primary), var(--secondary));
            border-radius: 50%;
            transform: translate(-50%, -50%);
            pointer-events: none;
            z-index: 1000;
            animation: beamBurst 0.6s ease-out forwards;
        `;
        
        // 添加爆发动画样式
        const style = document.createElement('style');
        style.textContent = `
            @keyframes beamBurst {
                0% {
                    width: 2px;
                    height: 2px;
                    opacity: 1;
                    transform: translate(-50%, -50%) scale(1);
                }
                50% {
                    width: 200px;
                    height: 200px;
                    opacity: 0.8;
                    transform: translate(-50%, -50%) scale(1);
                }
                100% {
                    width: 400px;
                    height: 400px;
                    opacity: 0;
                    transform: translate(-50%, -50%) scale(1);
                }
            }
        `;
        
        if (!document.querySelector('#beam-burst-style')) {
            style.id = 'beam-burst-style';
            document.head.appendChild(style);
        }
        
        card.appendChild(burst);
        
        // 动画完成后移除元素
        setTimeout(() => {
            if (burst.parentNode) {
                burst.parentNode.removeChild(burst);
            }
        }, 600);
    }

    renderFeaturedCharacters(characters) {
        const container = document.getElementById('featuredCharacters');
        container.innerHTML = '';
        
        const featuredCount = Math.min(3, characters.length);
        const featuredCharacters = characters.slice(0, featuredCount);
        
        // 创建Card Beam风格的三卡片容器
        const stackContainer = document.createElement('div');
        stackContainer.className = 'three-card-stack';
        stackContainer.id = 'threeCardStack';
        
        // 添加光束背景
        const beamBg = document.createElement('div');
        beamBg.className = 'card-beam-bg';
        stackContainer.appendChild(beamBg);
        
        // 创建卡片束容器
        const cardBeamStack = document.createElement('div');
        cardBeamStack.className = 'card-beam-stack';
        
        featuredCharacters.forEach((character, index) => {
            const characterCard = this.createStackCharacterCard(character, index);
            cardBeamStack.appendChild(characterCard);
        });
        
        stackContainer.appendChild(cardBeamStack);
        container.appendChild(stackContainer);
        
        // 添加Card Beam交互效果
        this.setupCardBeamInteractions();
    }

    createFeaturedCharacterCard(character, index) {
        const card = document.createElement('div');
        card.className = 'modern-character-card animate__animated animate__fadeInUp';
        card.onclick = () => this.selectCharacter(character.id);
        card.style.animationDelay = `${(index + 1) * 0.1}s`;
        
        const initials = character.name.substr(0, 2);
        const tags = character.tags ? character.tags.split(',').map(tag => tag.trim()) : [];
        const avatarUrl = character.avatarUrl || '/images/img.png';
        
        card.innerHTML = `
            <div class="modern-character-header">
                <div class="modern-character-avatar">
                    <img src="${avatarUrl}" alt="${character.name}" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                    <div class="modern-character-avatar-fallback" style="display: none;">${initials}</div>
                </div>
                <div class="modern-character-info">
                    <h3>${character.name}</h3>
                    <p>${character.category || 'AI角色'}</p>
                </div>
            </div>
            <div class="modern-character-description">
                ${character.description || '暂无描述'}
            </div>
            ${tags.length > 0 ? `
                <div class="modern-character-tags">
                    ${tags.slice(0, 3).map(tag => `<span class="modern-character-tag">${tag}</span>`).join('')}
                </div>
            ` : ''}
        `;
        
        return card;
    }
    
    /**
     * 创建Card Beam风格的角色卡片
     */
    createStackCharacterCard(character, index) {
        const card = document.createElement('div');
        card.className = 'stack-card';
        card.onclick = () => this.selectCharacter(character.id);
        
        const initials = character.name.substr(0, 2);
        const tags = character.tags ? character.tags.split(',').map(tag => tag.trim()) : [];
        const avatarUrl = character.avatarUrl || '/images/img.png';
        
        card.innerHTML = `
            <div class="stack-card-content">
                <div class="stack-card-header">
                    <div class="stack-card-avatar">
                        <img src="${avatarUrl}" alt="${character.name}" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                        <div class="stack-card-avatar-fallback" style="display: none;">${initials}</div>
                    </div>
                    <div class="stack-card-info">
                        <h3>${character.name}</h3>
                        <p>${character.category || 'AI角色'}</p>
                    </div>
                </div>
                <div class="stack-card-description">
                    ${character.description || '暂无描述'}
                </div>
                ${tags.length > 0 ? `
                    <div class="stack-card-tags">
                        ${tags.slice(0, 3).map(tag => `<span class="stack-card-tag">${tag}</span>`).join('')}
                    </div>
                ` : ''}
            </div>
        `;
        
        return card;
    }

    refreshCharacters() {
        if (this.allCharacters.length === 0) return;
        
        // 随机选择要显示的角色
        const shuffled = [...this.allCharacters].sort(() => 0.5 - Math.random());
        this.displayedCharacters = shuffled.slice(0, this.displayCount);
        this.renderCharacters(this.displayedCharacters);
        
        // 添加淡入动画
        const container = document.getElementById('characterList');
        container.style.opacity = '0';
        container.style.transform = 'translateY(20px)';
        
        setTimeout(() => {
            container.style.transition = 'all 0.5s ease';
            container.style.opacity = '1';
            container.style.transform = 'translateY(0)';
        }, 100);
    }
    
    createCharacterCard(character) {
        const card = document.createElement('div');
        card.className = 'modern-character-card animate__animated animate__fadeInUp';
        card.onclick = () => this.selectCharacter(character.id);
        
        const initials = character.name.substr(0, 2);
        const tags = character.tags ? character.tags.split(',').map(tag => tag.trim()) : [];
        const avatarUrl = character.avatarUrl || '/images/img.png';
        
        card.innerHTML = `
            <div class="modern-character-header">
                <div class="modern-character-avatar">
                    <img src="${avatarUrl}" alt="${character.name}" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
                    <div class="modern-character-avatar-fallback" style="display: none;">${initials}</div>
                </div>
                <div class="modern-character-info">
                    <h3>${character.name}</h3>
                    <p>${character.category || 'AI角色'}</p>
                </div>
            </div>
            <div class="modern-character-description">
                ${character.description || '暂无描述'}
            </div>
            ${tags.length > 0 ? `
                <div class="modern-character-tags">
                    ${tags.map(tag => `<span class="modern-character-tag">${tag}</span>`).join('')}
                </div>
            ` : ''}
        `;
        
        return card;
    }
    
    
    async showChatInterface() {
        console.log('showChatInterface called');
        console.log('Current character:', this.currentCharacter);
        
        const characterList = document.getElementById('characterList');
        const chatInterface = document.getElementById('chatInterface');
        
        console.log('characterList element:', characterList);
        console.log('chatInterface element:', chatInterface);
        
        if (!characterList || !chatInterface) {
            console.error('Required elements not found');
            return;
        }
        
        // 隐藏角色列表，显示聊天界面
        characterList.classList.add('hidden');
        chatInterface.classList.remove('hidden');
        
        console.log('Elements visibility updated');
        
        // 设置当前角色信息
        const avatar = document.getElementById('currentCharacterAvatar');
        const name = document.getElementById('currentCharacterName');
        const desc = document.getElementById('currentCharacterDesc');
        
        console.log('Character info elements:', {avatar, name, desc});
        
        if (avatar) {
            // 设置角色头像图片
            const avatarUrl = this.currentCharacter.avatarUrl || '/images/img.png';
            avatar.innerHTML = `
                <img src="${avatarUrl}" alt="${this.currentCharacter.name}" 
                     onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
                     style="width: 100%; height: 100%; object-fit: cover; border-radius: inherit;">
                <div class="modern-chat-character-avatar-fallback" style="display: none;">
                    ${this.currentCharacter.name.charAt(0)}
                </div>
            `;
        }
        if (name) name.textContent = this.currentCharacter.name;
        if (desc) desc.textContent = this.currentCharacter.description;
        
        // 清空聊天记录
        const chatMessages = document.getElementById('chatMessages');
        if (chatMessages) {
            chatMessages.innerHTML = '';
        }
        
        // 重置会话ID
        this.currentSession = null;
        
        // 加载对话历史
        await this.loadCharacterConversation();
        
        // 添加对话管理按钮
        this.addConversationControls();
        
        console.log('Chat interface setup complete');
    }
    
    addWelcomeMessage() {
        const welcomeMessages = {
            '哈利波特': '你好！我是哈利波特。很高兴在这里遇到你！你想聊些什么呢？也许是关于霍格沃茨的事情？',
            '苏格拉底': '欢迎，我的朋友。我是苏格拉底。让我们一起探索智慧的奥秘吧。你知道吗，我知道我一无所知。',
            '艾丽莎博士': '你好，我是艾丽莎博士。很高兴能与你交流。如果你有任何困扰或想聊的话题，我都很乐意倾听。'
        };
        
        const message = welcomeMessages[this.currentCharacter.name] || 
                       `你好！我是${this.currentCharacter.name}，很高兴与你聊天！`;
        
        this.addMessage('assistant', message, 'memory');
    }
    
    closeChat() {
        const characterList = document.getElementById('characterList');
        const chatInterface = document.getElementById('chatInterface');
        const featuredCharacters = document.getElementById('featuredCharacters');
        const refreshSection = document.querySelector('.modern-refresh-section');
        
        characterList.classList.remove('hidden');
        chatInterface.classList.add('hidden');
        
        // 恢复精选人物区域和换一批按钮的显示
        if (featuredCharacters) {
            featuredCharacters.style.display = 'block';
        }
        if (refreshSection) {
            refreshSection.style.display = 'block';
        }
        
        this.currentCharacter = null;
        this.currentSession = null;
    }
    
    setupEventListeners() {
        // 技能选择
        document.querySelectorAll('.modern-skill-selector, .skill-selector').forEach(selector => {
            selector.addEventListener('click', () => {
                // 移除其他技能的活动状态
                document.querySelectorAll('.modern-skill-selector, .skill-selector').forEach(s => s.classList.remove('active'));
                // 添加当前技能的活动状态
                selector.classList.add('active');
                this.selectedSkill = selector.dataset.skill;
            });
        });
        
        // 回车发送消息
        const messageInput = document.getElementById('messageInput');
        if (messageInput) {
            messageInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    this.sendMessage();
                } else if (e.key === 'Enter' && e.shiftKey) {
                    // Shift+Enter 允许换行
                }
            });
        }
        
        // 搜索框事件
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            // 输入事件 - 根据输入状态显示不同内容
            searchInput.addEventListener('input', (e) => {
                const keyword = e.target.value.trim();
                this.updateSearchClearButton();
                this.handleSearchInput(keyword);
            });
            
            // 回车键搜索事件
            searchInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    const keyword = e.target.value.trim();
                    if (keyword) {
                        this.searchCharacters(keyword, true); // 明确执行搜索，保存到历史记录
                    }
                }
            });
            
            searchInput.addEventListener('focus', () => {
                const keyword = searchInput.value.trim();
                this.handleSearchFocus(keyword);
            });
            
            searchInput.addEventListener('blur', () => {
                // 延迟关闭，允许点击建议项
                setTimeout(() => {
                    this.closeAllSearchDropdowns();
                }, 200);
            });
        }
    }
    
    async sendMessage() {
        const input = document.getElementById('messageInput');
        const message = input.value.trim();
        
        if (!message || !this.currentCharacter) {
            return;
        }
        
        // 检查登录状态
        if (!this.token || !this.currentUser) {
            this.showToast('聊天功能需要登录，请先登录', 'warning');
            // 显示登录模态框
            const loginModal = new bootstrap.Modal(document.getElementById('loginModal'));
            loginModal.show();
            return;
        }
        
        // 添加用户消息到界面
        this.addMessage('user', message);
        input.value = '';
        
        // 显示输入中状态
        this.showTypingIndicator();
        
        try {
            const chatRequest = {
                characterId: this.currentCharacter.id,
                message: message,
                sessionId: this.currentSession,
                preferredSkill: this.selectedSkill
            };
            
            const response = await this.fetchWithAuth('/api/chat/send', {
                method: 'POST',
                body: JSON.stringify(chatRequest)
            });
            
            if (response.ok) {
                const chatResponse = await response.json();
                
                if (chatResponse.success) {
                    this.currentSession = chatResponse.sessionId;
                    this.hideTypingIndicator();
                    this.addMessage('assistant', chatResponse.message, chatResponse.skillUsed, chatResponse.audioUrl);
                    
                    // 如果有语音回复，播放语音
                    if (chatResponse.audioUrl) {
                        this.playAudio(chatResponse.audioUrl);
                    } else {
                        // 使用TTS生成语音
                        this.generateTTS(chatResponse.message);
                    }
                    
                    // 显示情感检测结果
                    if (chatResponse.emotionDetected && chatResponse.emotionDetected !== 'neutral') {
                        this.showEmotionDetection(chatResponse.emotionDetected);
                    }
                } else {
                    this.hideTypingIndicator();
                    this.addMessage('assistant', chatResponse.errorMessage || '抱歉，出现了错误');
                }
            } else {
                this.hideTypingIndicator();
                this.addMessage('assistant', '网络错误，请稍后再试');
            }
        } catch (error) {
            console.error('发送消息失败:', error);
            this.hideTypingIndicator();
            this.addMessage('assistant', '发送失败，请检查网络连接');
        }
    }
    
    addMessage(type, content, skill = null, audioUrl = null, isVoiceMessage = false) {
        const messagesContainer = document.getElementById('chatMessages');
        const messageDiv = document.createElement('div');
        messageDiv.className = `modern-message ${type} animate__animated animate__fadeInUp`;
        
        let skillBadge = '';
        if (skill && type === 'assistant') {
            const skillNames = {
                'knowledge': '知识问答',
                'emotion': '情感感知',
                'creative': '创意写作',
                'memory': '记忆管理',
                'analyze': '深度分析'
            };
            skillBadge = `<div class="mb-2"><span class="skill-badge skill-${skill}">${skillNames[skill] || skill}</span></div>`;
        }
        
        // 根据消息类型设置头像
        let avatarHtml;
        if (type === 'user') {
            avatarHtml = '<div class="modern-message-avatar">我</div>';
        } else {
            const avatarUrl = this.currentCharacter?.avatarUrl || '/images/img.png';
            avatarHtml = `
                <div class="modern-message-avatar">
                    <img src="${avatarUrl}" alt="${this.currentCharacter?.name || 'AI'}" 
                         onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
                         style="width: 100%; height: 100%; object-fit: cover; border-radius: inherit;">
                    <div class="modern-message-avatar-fallback" style="display: none;">
                        ${this.currentCharacter?.name?.charAt(0) || 'AI'}
                    </div>
                </div>
            `;
        }
        
        // 语音消息标识
        let voiceIndicator = '';
        if (isVoiceMessage) {
            voiceIndicator = `<div class="voice-message-indicator">
                <i class="bi bi-mic-fill"></i>
                <span>语音消息</span>
            </div>`;
        }
        
        messageDiv.innerHTML = `
            ${avatarHtml}
            <div class="modern-message-content">
                ${skillBadge}
                ${voiceIndicator}
                <p class="modern-message-text">${content}</p>
                ${type === 'assistant' ? `
                    <div class="message-actions">
                        <button class="play-btn" onclick="app.speakMessage(this)" data-audio-url="${audioUrl || ''}" title="播放语音">
                            <i class="bi bi-volume-up"></i>
                        </button>
                        <button class="copy-btn" onclick="app.copyMessage(this)" title="复制消息">
                            <i class="bi bi-copy"></i>
                        </button>
                        <button class="regenerate-btn" onclick="app.regenerateMessage(this)" title="重新回答">
                            <i class="bi bi-arrow-clockwise"></i>
                        </button>
                    </div>
                ` : ''}
            </div>
        `;
        
        // 保存音频URL到消息元素中
        if (audioUrl) {
            messageDiv.setAttribute('data-audio-url', audioUrl);
        }
        
        messagesContainer.appendChild(messageDiv);
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
    }
    
    showTypingIndicator() {
        const indicator = document.createElement('div');
        indicator.id = 'typingIndicator';
        indicator.className = 'modern-message assistant animate__animated animate__fadeIn';
        const avatarUrl = this.currentCharacter?.avatarUrl || '/images/img.png';
        indicator.innerHTML = `
            <div class="modern-message-avatar">
                <img src="${avatarUrl}" alt="${this.currentCharacter?.name || 'AI'}" 
                     onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
                     style="width: 100%; height: 100%; object-fit: cover; border-radius: inherit;">
                <div class="modern-message-avatar-fallback" style="display: none;">
                    ${this.currentCharacter?.name?.charAt(0) || 'AI'}
                </div>
            </div>
            <div class="modern-message-content">
                <div class="d-flex align-items-center">
                    <div class="modern-loading">
                        <div class="modern-loading-dot"></div>
                        <div class="modern-loading-dot"></div>
                        <div class="modern-loading-dot"></div>
                    </div>
                    <span class="ms-2">AI正在思考中...</span>
                </div>
            </div>
        `;
        
        document.getElementById('chatMessages').appendChild(indicator);
        document.getElementById('chatMessages').scrollTop = document.getElementById('chatMessages').scrollHeight;
    }
    
    hideTypingIndicator() {
        const indicator = document.getElementById('typingIndicator');
        if (indicator) {
            indicator.remove();
        }
    }
    
    async generateTTS(text) {
        try {
            const response = await this.fetchWithAuth('/api/voice/tts', {
                method: 'POST',
                body: JSON.stringify({
                    text: text,
                    characterName: this.currentCharacter.name
                })
            });
            
            if (response.ok) {
                const result = await response.json();
                if (result.success && result.audioUrl) {
                    this.playAudio(result.audioUrl);
                }
            }
        } catch (error) {
            console.error('TTS生成失败:', error);
        }
    }
    
    playAudio(audioUrl) {
        console.log('开始播放音频:', audioUrl);
        
        // 如果当前有音频在播放，先停止
        if (this.currentAudio && !this.currentAudio.paused) {
            this.currentAudio.pause();
            this.isPlaying = false;
        }
        
        const audio = new Audio(audioUrl);
        this.currentAudio = audio;
        
        // 添加音频事件监听器
        audio.addEventListener('loadstart', () => console.log('音频开始加载'));
        audio.addEventListener('loadeddata', () => console.log('音频数据加载完成'));
        audio.addEventListener('canplay', () => console.log('音频可以播放'));
        audio.addEventListener('play', () => {
            console.log('音频开始播放');
            this.isPlaying = true;
            // 更新所有播放按钮图标为暂停状态
            try {
                this.updatePlayButtons('pause');
            } catch (error) {
                console.warn('更新播放按钮状态失败:', error);
            }
        });
        audio.addEventListener('pause', () => {
            console.log('音频暂停');
            this.isPlaying = false;
            // 更新所有播放按钮图标为播放状态
            try {
                this.updatePlayButtons('play');
            } catch (error) {
                console.warn('更新播放按钮状态失败:', error);
            }
        });
        audio.addEventListener('ended', () => {
            console.log('音频播放结束');
            this.isPlaying = false;
            // 只有在音频真正结束时才清除引用，这样下次点击会重新生成TTS
            this.currentAudio = null;
            // 更新所有播放按钮图标为播放状态
            try {
                this.updatePlayButtons('play');
            } catch (error) {
                console.warn('更新播放按钮状态失败:', error);
            }
        });
        audio.addEventListener('error', (e) => {
            console.error('音频加载错误:', e);
            this.isPlaying = false;
            this.currentAudio = null;
        });
        
        // 设置音量并播放
        audio.volume = 0.8;
        audio.play().catch(error => {
            console.error('音频播放失败:', error);
            this.isPlaying = false;
            this.currentAudio = null;
            // 显示错误提示
            this.showToast('音频播放失败，可能是音频格式不支持', 'error');
        });
    }
    
    speakMessage(button) {
        // 获取消息文本 - 从消息容器中查找 .modern-message-text 元素
        const messageContainer = button.closest('.modern-message');
        if (!messageContainer) {
            console.error('无法找到消息容器，按钮可能不在正确的消息结构中');
            this.showToast('无法播放此消息，消息结构异常', 'error');
            return;
        }
        
        const messageTextElement = messageContainer.querySelector('.modern-message-text');
        const messageText = messageTextElement ? messageTextElement.textContent.trim() : '';
        
        console.log('speakMessage - 消息文本:', messageText);
        console.log('speakMessage - 按钮data-audio-url:', button.getAttribute('data-audio-url'));
        
        // 如果当前正在播放，则暂停
        if (this.isPlaying && this.currentAudio) {
            this.currentAudio.pause();
            this.isPlaying = false;
            return;
        }
        
        // 如果当前有暂停的音频，则继续播放
        if (this.currentAudio && this.currentAudio.paused) {
            this.currentAudio.play();
            return;
        }
        
        // 优先使用缓存的音频URL
        const cachedAudioUrl = button.getAttribute('data-audio-url');
        if (cachedAudioUrl && cachedAudioUrl.trim() !== '') {
            console.log('使用缓存的音频URL:', cachedAudioUrl);
            this.playAudio(cachedAudioUrl);
            return;
        }
        
        // 如果当前没有音频或音频已结束，则重新生成TTS
        if (messageText) {
            this.generateTTS(messageText);
        } else {
            console.error('无法获取消息文本');
        }
    }

    copyMessage(button) {
        // 获取消息文本
        const messageContainer = button.closest('.modern-message');
        if (!messageContainer) {
            console.error('无法找到消息容器，按钮可能不在正确的消息结构中');
            this.showToast('无法复制此消息，消息结构异常', 'error');
            return;
        }
        
        const messageTextElement = messageContainer.querySelector('.modern-message-text');
        const messageText = messageTextElement ? messageTextElement.textContent.trim() : '';
        
        if (!messageText) {
            this.showToast('消息内容为空，无法复制', 'warning');
            return;
        }
        
        try {
            // 使用 Clipboard API 复制文本
            navigator.clipboard.writeText(messageText).then(() => {
                this.showToast('消息已复制到剪贴板', 'success');
                
                // 临时更改按钮图标以提供视觉反馈
                const icon = button.querySelector('i');
                const originalClass = icon.className;
                icon.className = 'bi bi-check';
                
                setTimeout(() => {
                    icon.className = originalClass;
                }, 1000);
            }).catch(error => {
                console.error('复制失败:', error);
                this.showToast('复制失败，请手动选择文本复制', 'error');
            });
        } catch (error) {
            console.error('复制操作不支持:', error);
            this.showToast('浏览器不支持自动复制，请手动选择文本复制', 'error');
        }
    }

    async regenerateMessage(button) {
        // 获取消息容器
        const messageContainer = button.closest('.modern-message');
        if (!messageContainer) {
            console.error('无法找到消息容器，按钮可能不在正确的消息结构中');
            this.showToast('无法重新生成此消息，消息结构异常', 'error');
            return;
        }

        // 检查是否有当前角色和会话
        if (!this.currentCharacter) {
            this.showToast('请先选择一个角色', 'warning');
            return;
        }

        // 检查登录状态
        if (!this.token || !this.currentUser) {
            this.showToast('重新生成回答需要登录，请先登录', 'warning');
            return;
        }

        // 找到用户的上一条消息作为重新生成的输入
        const allMessages = Array.from(document.querySelectorAll('.modern-message'));
        const currentIndex = allMessages.indexOf(messageContainer);
        
        let userMessage = '';
        // 向前查找最近的用户消息
        for (let i = currentIndex - 1; i >= 0; i--) {
            if (allMessages[i].classList.contains('user')) {
                const userMessageElement = allMessages[i].querySelector('.modern-message-text');
                userMessage = userMessageElement ? userMessageElement.textContent.trim() : '';
                break;
            }
        }

        if (!userMessage) {
            this.showToast('无法找到对应的用户消息，无法重新生成', 'error');
            return;
        }

        try {
            // 临时更改按钮图标显示加载状态
            const icon = button.querySelector('i');
            const originalClass = icon.className;
            icon.className = 'bi bi-arrow-repeat';
            button.disabled = true;

            // 发送请求重新生成回答
            const chatRequest = {
                characterId: this.currentCharacter.id,
                message: userMessage,
                sessionId: this.currentSession,
                preferredSkill: this.selectedSkill
            };

            const response = await this.fetchWithAuth('/api/chat/send', {
                method: 'POST',
                body: JSON.stringify(chatRequest)
            });

            if (response.ok) {
                const chatResponse = await response.json();
                
                if (chatResponse.success) {
                    // 更新当前消息的内容
                    const messageTextElement = messageContainer.querySelector('.modern-message-text');
                    if (messageTextElement) {
                        messageTextElement.textContent = chatResponse.message;
                    }

                    // 更新音频URL
                    const playBtn = messageContainer.querySelector('.play-btn');
                    if (playBtn && chatResponse.audioUrl) {
                        playBtn.setAttribute('data-audio-url', chatResponse.audioUrl);
                        messageContainer.setAttribute('data-audio-url', chatResponse.audioUrl);
                    }

                    // 更新技能标签
                    if (chatResponse.skillUsed) {
                        const skillBadge = messageContainer.querySelector('.skill-badge');
                        if (skillBadge) {
                            const skillNames = {
                                'knowledge': '知识问答',
                                'emotion': '情感感知', 
                                'creative': '创意写作',
                                'memory': '记忆管理',
                                'analyze': '深度分析'
                            };
                            skillBadge.textContent = skillNames[chatResponse.skillUsed] || chatResponse.skillUsed;
                            skillBadge.className = `skill-badge skill-${chatResponse.skillUsed}`;
                        }
                    }

                    this.showToast('回答已重新生成', 'success');

                    // 如果有新的语音，可以自动播放
                    if (chatResponse.audioUrl) {
                        this.playAudio(chatResponse.audioUrl);
                    } else {
                        // 使用TTS生成语音
                        this.generateTTS(chatResponse.message);
                    }

                    // 显示情感检测结果
                    if (chatResponse.emotionDetected && chatResponse.emotionDetected !== 'neutral') {
                        this.showEmotionDetection(chatResponse.emotionDetected);
                    }
                } else {
                    this.showToast(chatResponse.errorMessage || '重新生成失败', 'error');
                }
            } else {
                this.showToast('网络错误，请稍后再试', 'error');
            }
        } catch (error) {
            console.error('重新生成消息失败:', error);
            this.showToast('重新生成失败，请检查网络连接', 'error');
        } finally {
            // 恢复按钮状态
            icon.className = originalClass;
            button.disabled = false;
        }
    }
    
    updatePlayButtons(state) {
        // 更新所有播放按钮的图标
        const playButtons = document.querySelectorAll('button[onclick*="speakMessage"]');
        playButtons.forEach(button => {
            try {
                if (state === 'pause') {
                    button.innerHTML = '<i class="bi bi-pause"></i>';
                } else {
                    button.innerHTML = '<i class="bi bi-volume-up"></i>';
                }
            } catch (error) {
                console.warn('更新播放按钮失败:', error);
            }
        });
    }
    
    async toggleVoiceRecording() {
        const voiceBtn = document.getElementById('voiceBtn');
        
        if (!this.isRecording) {
            try {
                // 配置更好的音频录制参数
                const constraints = {
                    audio: {
                        sampleRate: 16000,      // 百度推荐的采样率
                        channelCount: 1,        // 单声道
                        echoCancellation: true, // 回声消除
                        noiseSuppression: true, // 噪声抑制
                        autoGainControl: true   // 自动增益控制
                    }
                };
                
                const stream = await navigator.mediaDevices.getUserMedia(constraints);
                
                // 尝试指定录音格式
                let options = {};
                if (MediaRecorder.isTypeSupported('audio/wav')) {
                    options.mimeType = 'audio/wav';
                } else if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
                    options.mimeType = 'audio/webm;codecs=opus';
                } else if (MediaRecorder.isTypeSupported('audio/mp4')) {
                    options.mimeType = 'audio/mp4';
                }
                
                console.log('录音配置:', constraints, '格式:', options.mimeType || '默认');
                this.mediaRecorder = new MediaRecorder(stream, options);
                this.audioChunks = [];
                
                this.mediaRecorder.ondataavailable = (event) => {
                    this.audioChunks.push(event.data);
                };
                
                this.mediaRecorder.onstop = async () => {
                    // 使用录制时的实际格式
                    const mimeType = this.mediaRecorder.mimeType || 'audio/webm;codecs=opus';
                    const rawBlob = new Blob(this.audioChunks, { type: mimeType });
                    
                    console.log('录音完成(原始):', {
                        size: rawBlob.size,
                        type: rawBlob.type,
                        duration: 'unknown'
                    });
                    
                    // 转换为16k单声道WAV，提升ASR识别效果
                    let wavBlob;
                    try {
                        wavBlob = await this.convertTo16kMonoWav(rawBlob);
                        console.log('转换完成(WAV 16k mono):', { size: wavBlob.size, type: wavBlob.type });
                    } catch (e) {
                        console.warn('音频转换为WAV失败，回退上传原始格式:', e);
                        wavBlob = rawBlob;
                    }
                    
                    this.sendVoiceMessage(wavBlob);
                    stream.getTracks().forEach(track => track.stop());
                };
                
                this.mediaRecorder.start();
                this.isRecording = true;
                voiceBtn.classList.add('recording');
                voiceBtn.innerHTML = '<i class="bi bi-mic-fill"></i>';
                
            } catch (error) {
                console.error('无法访问麦克风:', error);
                alert('无法访问麦克风，请检查权限设置');
            }
        } else {
            this.mediaRecorder.stop();
            this.isRecording = false;
            voiceBtn.classList.remove('recording');
            voiceBtn.innerHTML = '<i class="bi bi-mic"></i>';
        }
    }
    
    async loadVoiceRecognitionStrategies() {
        try {
            const response = await fetch('/api/voice/strategies');
            if (response.ok) {
                const result = await response.json();
                if (result.success) {
                    this.availableStrategies = result.strategies;
                    this.updateStrategySelector();
                    
                    // 如果没有选择的策略或策略不可用，使用默认策略
                    if (!this.selectedStrategy || !this.availableStrategies[this.selectedStrategy]) {
                        this.selectedStrategy = result.defaultStrategy;
                        localStorage.setItem('selectedAsrStrategy', this.selectedStrategy);
                    }
                    
                    console.log('语音识别策略加载成功:', this.availableStrategies);
                }
            }
        } catch (error) {
            console.error('加载语音识别策略失败:', error);
        }
    }
    
    updateStrategySelector() {
        const strategyBtn = document.getElementById('voiceStrategyBtn');
        const strategyName = document.getElementById('strategyName');
        const strategyDropdown = document.getElementById('strategyDropdown');
        
        if (!strategyBtn || !strategyName || !strategyDropdown) return;
        
        // 更新按钮显示的策略名称
        const currentStrategy = this.availableStrategies[this.selectedStrategy];
        if (currentStrategy) {
            strategyName.textContent = currentStrategy.displayName;
        } else {
            strategyName.textContent = '请选择';
        }
        
        // 清空下拉菜单
        strategyDropdown.innerHTML = '';
        
        // 添加策略选项
        Object.entries(this.availableStrategies).forEach(([name, info]) => {
            const option = document.createElement('div');
            option.className = 'strategy-option';
            option.dataset.strategy = name;
            
            if (!info.available) {
                option.classList.add('disabled');
            }
            
            if (name === this.selectedStrategy) {
                option.classList.add('active');
            }
            
            option.innerHTML = `
                <i class="bi bi-mic-fill"></i>
                <span>${info.displayName}</span>
                <span class="strategy-status">${info.available ? '可用' : '不可用'}</span>
            `;
            
            // 添加点击事件
            option.addEventListener('click', () => {
                if (!info.available) return;
                
                this.selectedStrategy = name;
                localStorage.setItem('selectedAsrStrategy', this.selectedStrategy);
                console.log('切换语音识别策略:', this.selectedStrategy);
                
                // 更新UI
                this.updateStrategySelector();
                this.hideStrategyDropdown();
                
                this.showToast(`已切换到${info.displayName}`, 'success');
            });
            
            strategyDropdown.appendChild(option);
        });
        
        // 设置按钮点击事件（只设置一次）
        if (!strategyBtn.hasAttribute('data-initialized')) {
            strategyBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                this.toggleStrategyDropdown();
            });
            
            // 点击其他地方关闭下拉菜单
            document.addEventListener('click', (e) => {
                if (!strategyBtn.contains(e.target) && !strategyDropdown.contains(e.target)) {
                    this.hideStrategyDropdown();
                }
            });
            
            strategyBtn.setAttribute('data-initialized', 'true');
        }
    }
    
    toggleStrategyDropdown() {
        const strategyBtn = document.getElementById('voiceStrategyBtn');
        const strategyDropdown = document.getElementById('strategyDropdown');
        
        if (!strategyBtn || !strategyDropdown) return;
        
        const isOpen = strategyDropdown.classList.contains('show');
        
        if (isOpen) {
            this.hideStrategyDropdown();
        } else {
            this.showStrategyDropdown();
        }
    }
    
    showStrategyDropdown() {
        const strategyBtn = document.getElementById('voiceStrategyBtn');
        const strategyDropdown = document.getElementById('strategyDropdown');
        
        if (!strategyBtn || !strategyDropdown) return;
        
        strategyBtn.classList.add('open');
        strategyDropdown.classList.add('show');
    }
    
    hideStrategyDropdown() {
        const strategyBtn = document.getElementById('voiceStrategyBtn');
        const strategyDropdown = document.getElementById('strategyDropdown');
        
        if (!strategyBtn || !strategyDropdown) return;
        
        strategyBtn.classList.remove('open');
        strategyDropdown.classList.remove('show');
    }

    async sendVoiceMessage(audioBlob) {
        const formData = new FormData();
        const fileName = (audioBlob && audioBlob.type && audioBlob.type.includes('wav')) ? 'voice.wav' : 'voice.webm';
        formData.append('audio', audioBlob, fileName);
        
        // 添加策略参数
        if (this.selectedStrategy) {
            formData.append('strategy', this.selectedStrategy);
        }
        
        try {
            const headers = {};
            if (this.token) {
                headers['Authorization'] = `Bearer ${this.token}`;
            }
            
            const response = await fetch('/api/voice/asr', {
                method: 'POST',
                headers: headers,
                body: formData
            });
            
            if (response.ok) {
                const result = await response.json();
                if (result.success && result.text) {
                    document.getElementById('messageInput').value = result.text;
                    console.log(`使用${result.strategyDisplayName}识别成功:`, result.text);
                    // 语音识别完成后自动发送消息
                    this.sendMessage();
                } else {
                    console.warn('语音识别失败:', result);
                    this.showToast(`语音识别失败: ${result.error || '未知错误'}`, 'error');
                }
            }
        } catch (error) {
            console.error('语音识别失败:', error);
            this.showToast('语音识别服务异常', 'error');
        }
    }

    // 将任意音频Blob转换为 16kHz 单声道 WAV
    async convertTo16kMonoWav(inputBlob) {
        const arrayBuffer = await inputBlob.arrayBuffer();
        const audioCtx = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 16000 * 10, 16000); // 最长10秒缓冲
        const tempCtx = new (window.AudioContext || window.webkitAudioContext)();
        try {
            const decoded = await tempCtx.decodeAudioData(arrayBuffer.slice(0));
            // 重采样到16k，转换为单声道
            const duration = Math.min(decoded.duration, 10); // 最长10秒，避免超大
            const offlineCtx = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, Math.ceil(16000 * duration), 16000);
            const source = offlineCtx.createBufferSource();
            // down-mix to mono manually if needed
            const monoBuffer = offlineCtx.createBuffer(1, decoded.length, decoded.sampleRate);
            const channelData = monoBuffer.getChannelData(0);
            const ch0 = decoded.getChannelData(0);
            if (decoded.numberOfChannels > 1) {
                const ch1 = decoded.getChannelData(1);
                const len = Math.min(ch0.length, ch1.length);
                for (let i = 0; i < len; i++) channelData[i] = (ch0[i] + ch1[i]) / 2;
            } else {
                channelData.set(ch0);
            }
            source.buffer = monoBuffer;
            source.connect(offlineCtx.destination);
            source.start();
            const rendered = await offlineCtx.startRendering();
            const wavBlob = this.encodeWav(rendered, 16000);
            return wavBlob;
        } finally {
            tempCtx.close();
        }
    }

    // 将AudioBuffer编码为16-bit PCM WAV
    encodeWav(audioBuffer, sampleRate) {
        const numChannels = 1;
        const samples = audioBuffer.getChannelData(0);
        const buffer = new ArrayBuffer(44 + samples.length * 2);
        const view = new DataView(buffer);

        // RIFF/WAVE header
        this.writeString(view, 0, 'RIFF');
        view.setUint32(4, 36 + samples.length * 2, true);
        this.writeString(view, 8, 'WAVE');
        this.writeString(view, 12, 'fmt ');
        view.setUint32(16, 16, true); // PCM chunk size
        view.setUint16(20, 1, true);  // PCM format
        view.setUint16(22, numChannels, true);
        view.setUint32(24, sampleRate, true);
        view.setUint32(28, sampleRate * numChannels * 2, true); // byte rate
        view.setUint16(32, numChannels * 2, true); // block align
        view.setUint16(34, 16, true); // bits per sample
        this.writeString(view, 36, 'data');
        view.setUint32(40, samples.length * 2, true);

        // PCM samples
        let offset = 44;
        for (let i = 0; i < samples.length; i++, offset += 2) {
            let s = Math.max(-1, Math.min(1, samples[i]));
            view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
        }

        return new Blob([view], { type: 'audio/wav' });
    }

    writeString(view, offset, string) {
        for (let i = 0; i < string.length; i++) {
            view.setUint8(offset + i, string.charCodeAt(i));
        }
    }
    
    async searchCharacters(keyword = null, saveToHistory = true) {
        const searchInput = document.getElementById('searchInput');
        const searchTerm = keyword || searchInput.value.trim();
        
        // 添加到搜索历史（只有在明确执行搜索时才保存）
        if (searchTerm && saveToHistory) {
            this.addToSearchHistory(searchTerm);
        }
        
        try {
            const url = searchTerm ? `/api/characters/search?keyword=${encodeURIComponent(searchTerm)}` : '/api/characters';
            const response = await fetch(url);
            
            if (response.ok) {
                const characters = await response.json();
                this.renderCharacters(characters);
                
                // 显示搜索结果，隐藏其他区域
                const characterList = document.getElementById('characterList');
                const chatInterface = document.getElementById('chatInterface');
                const featuredCharacters = document.getElementById('featuredCharacters');
                const refreshSection = document.querySelector('.modern-refresh-section');
                
                if (characterList && chatInterface) {
                    characterList.classList.remove('hidden');
                    chatInterface.classList.add('hidden');
                    
                    // 隐藏精选人物区域和换一批按钮
                    if (featuredCharacters) {
                        featuredCharacters.style.display = 'none';
                    }
                    if (refreshSection) {
                        refreshSection.style.display = 'none';
                    }
                }
            }
        } catch (error) {
            console.error('搜索失败:', error);
        }
    }
    

    // 处理搜索输入
    handleSearchInput(keyword) {
        if (!keyword || keyword.length < 1) {
            // 没有输入时显示历史记录
            this.showSearchHistory();
        } else {
            // 有输入时直接搜索并显示结果
            this.hideSearchHistory();
            this.searchCharacters(keyword, false); // 不保存到历史记录，因为只是输入过程
        }
    }

    // 处理搜索框获得焦点
    handleSearchFocus(keyword) {
        if (!keyword || keyword.length < 1) {
            // 没有输入时显示历史记录
            this.showSearchHistory();
        } else {
            // 有输入时直接搜索并显示结果
            this.searchCharacters(keyword, false); // 不保存到历史记录，因为只是获得焦点
        }
    }

    // 显示搜索历史
    showSearchHistory() {
        const horizontal = document.getElementById('searchHistoryHorizontal');
        
        if (horizontal) {
            this.updateSearchHistoryHorizontal();
            horizontal.style.display = 'block';
        }
    }

    // 隐藏搜索历史
    hideSearchHistory() {
        const horizontal = document.getElementById('searchHistoryHorizontal');
        
        if (horizontal) {
            horizontal.style.display = 'none';
        }
    }

    // 关闭所有搜索下拉框
    closeAllSearchDropdowns() {
        this.hideSearchHistory();
    }
    
    selectCharacter(characterId) {
        console.log('selectCharacter called with ID:', characterId, 'type:', typeof characterId);
        
        // 确保characterId是数字类型
        const id = typeof characterId === 'string' ? parseInt(characterId) : characterId;
        
        // 首先尝试从本地数据中查找
        let character = null;
        if (this.allCharacters && this.allCharacters.length > 0) {
            character = this.allCharacters.find(c => c.id === id);
        }
        
        // 如果没找到，从后端API获取所有角色并查找
        if (!character) {
            console.log('从后端API获取所有角色');
            this.fetchAllCharactersAndSelect(id);
            return;
        }
        
        console.log('Found character:', character);
        
        if (character) {
            this.currentCharacter = character;
            console.log('Setting current character:', this.currentCharacter);
            this.showChatInterface();
            this.closeAllSearchDropdowns();
        } else {
            console.error('Character not found with ID:', characterId);
            this.showToast('未找到指定的角色', 'error');
        }
    }
    
    // 从后端API获取所有角色并选择指定角色
    async fetchAllCharactersAndSelect(characterId) {
        try {
            const response = await fetch('/api/characters');
            if (response.ok) {
                const characters = await response.json();
                const character = characters.find(c => c.id === characterId);
                if (character) {
                    this.currentCharacter = character;
                    console.log('从后端获取角色成功:', character);
                    this.showChatInterface();
                    this.closeAllSearchDropdowns();
                } else {
                    console.error('角色未找到:', characterId);
                    this.showToast('未找到指定的角色', 'error');
                }
            } else {
                console.error('获取角色列表失败:', response.status);
                this.showToast('获取角色列表失败', 'error');
            }
        } catch (error) {
            console.error('获取角色列表失败:', error);
            this.showToast('获取角色列表失败', 'error');
        }
    }
    
    updateSearchClearButton() {
        const searchInput = document.getElementById('searchInput');
        const clearBtn = document.getElementById('searchClearBtn');
        const searchBtn = document.getElementById('searchBtn');
        
        if (searchInput.value.trim()) {
            clearBtn.classList.add('show');
            searchBtn.classList.add('show');
        } else {
            clearBtn.classList.remove('show');
            searchBtn.classList.remove('show');
        }
    }
    
    clearSearch() {
        document.getElementById('searchInput').value = '';
        this.closeAllSearchDropdowns();
        this.updateSearchClearButton();
    }
    
    // 刷新本地缓存
    async refreshLocalCache() {
        try {
            console.log('正在刷新本地缓存...');
            await this.loadCharacters();
            this.showToast('本地缓存已刷新', 'success');
        } catch (error) {
            console.error('刷新本地缓存失败:', error);
            this.showToast('刷新缓存失败', 'error');
        }
    }
    
    showEmotionDetection(emotion) {
        const emotionMap = {
            'happy': { text: '开心', icon: '😊', color: '#28a745' },
            'sad': { text: '难过', icon: '😢', color: '#6c757d' },
            'angry': { text: '生气', icon: '😠', color: '#dc3545' },
            'anxious': { text: '焦虑', icon: '😰', color: '#ffc107' },
            'confused': { text: '困惑', icon: '🤔', color: '#17a2b8' },
            'surprised': { text: '惊讶', icon: '😲', color: '#e83e8c' }
        };
        
        const emotionInfo = emotionMap[emotion];
        if (emotionInfo) {
            const toast = document.createElement('div');
            toast.className = 'toast show position-fixed top-0 end-0 m-3';
            toast.style.zIndex = '9999';
            toast.innerHTML = `
                <div class="toast-body bg-light">
                    <span style="color: ${emotionInfo.color}; font-size: 1.2rem;">
                        ${emotionInfo.icon} 检测到情感: ${emotionInfo.text}
                    </span>
                </div>
            `;
            
            document.body.appendChild(toast);
            setTimeout(() => toast.remove(), 3000);
        }
    }

    // 认证相关方法
    async checkLoginStatus() {
        if (this.token) {
            try {
                const response = await this.fetchWithAuth('/api/auth/me');
                if (response.ok) {
                    this.currentUser = await response.json();
                    this.updateUserInterface();
                } else {
                    // Token 过期或无效
                    this.logout();
                }
            } catch (error) {
                console.error('检查登录状态失败:', error);
                this.logout();
            }
        }
    }

    updateUserInterface() {
        const userInfo = document.getElementById('userInfo');
        const loginButtons = document.getElementById('loginButtons');
        const username = document.getElementById('username');
        const usernameLarge = document.getElementById('usernameLarge');

        if (this.currentUser) {
            const displayName = this.currentUser.nickname || this.currentUser.username;
            username.textContent = displayName;
            if (usernameLarge) {
                usernameLarge.textContent = displayName;
            }
            userInfo.classList.remove('hidden');
            loginButtons.classList.add('hidden');
        } else {
            userInfo.classList.add('hidden');
            loginButtons.classList.remove('hidden');
        }
    }

    async fetchWithAuth(url, options = {}) {
        const defaultHeaders = {
            ...(this.token && { 'Authorization': `Bearer ${this.token}` })
        };
        
        // 如果不是FormData，则添加JSON Content-Type
        if (!(options.body instanceof FormData)) {
            defaultHeaders['Content-Type'] = 'application/json';
        }
        
        const defaultOptions = {
            headers: {
                ...defaultHeaders,
                ...(options.headers || {})
            }
        };

        return fetch(url, { ...defaultOptions, ...options });
    }

    setupAuthListeners() {
        // 登录表单
        document.getElementById('loginForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const usernameOrEmail = document.getElementById('loginUsernameOrEmail').value;
            const password = document.getElementById('loginPassword').value;

            try {
                const response = await fetch('/api/auth/login', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ usernameOrEmail, password })
                });

                const result = await response.json();
                if (result.success) {
                    this.token = result.token;
                    this.currentUser = result.user;
                    localStorage.setItem('token', this.token);
                    this.updateUserInterface();
                    
                    // 隐藏登录模态框
                    const modal = bootstrap.Modal.getInstance(document.getElementById('loginModal'));
                    modal.hide();
                    
                    this.showToast('登录成功！', 'success');
                } else {
                    const errorElement = document.getElementById('loginError');
                    errorElement.textContent = result.message;
                    errorElement.classList.remove('hidden');
                }
            } catch (error) {
                console.error('登录失败:', error);
                const errorElement = document.getElementById('loginError');
                errorElement.textContent = '网络错误，请稍后再试';
                errorElement.classList.remove('hidden');
            }
        });

        // 注册表单
        document.getElementById('registerForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const username = document.getElementById('registerUsername').value;
            const email = document.getElementById('registerEmail').value;
            const password = document.getElementById('registerPassword').value;
            const nickname = document.getElementById('registerNickname').value;

            try {
                const response = await fetch('/api/auth/register', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ username, email, password, nickname })
                });

                const result = await response.json();
                if (result.success) {
                    this.token = result.token;
                    this.currentUser = result.user;
                    localStorage.setItem('token', this.token);
                    this.updateUserInterface();
                    
                    // 隐藏注册模态框
                    const modal = bootstrap.Modal.getInstance(document.getElementById('registerModal'));
                    modal.hide();
                    
                    this.showToast('注册成功！', 'success');
                } else {
                    const errorElement = document.getElementById('registerError');
                    errorElement.textContent = result.message;
                    errorElement.classList.remove('hidden');
                }
            } catch (error) {
                console.error('注册失败:', error);
                const errorElement = document.getElementById('registerError');
                errorElement.textContent = '网络错误，请稍后再试';
                errorElement.classList.remove('hidden');
            }
        });
    }

    logout() {
        this.token = null;
        this.currentUser = null;
        localStorage.removeItem('token');
        this.updateUserInterface();
        this.showToast('已退出登录', 'info');
    }

    async loadChatHistory(event = null) {
        if (event) {
            event.stopPropagation();
        }
        
        if (!this.currentUser) {
            this.showToast('请先登录查看对话历史', 'warning');
            return;
        }

        // 如果对话历史栏是展开的，重新加载
        if (this.sectionStates.chatHistory.expanded) {
            this.loadChatHistoryPage();
        } else {
            // 如果未展开，先展开再加载
            this.toggleSection('chatHistory');
        }
    }
    
    /**
     * 刷新聊天历史
     */
    refreshChatHistory(event = null) {
        if (event) {
            event.stopPropagation();
        }
        
        if (!this.currentUser) {
            this.showToast('请先登录查看对话历史', 'warning');
            return;
        }
        
        // 强制刷新聊天历史数据
        this.forceRefreshData('chatHistory').then(() => {
            if (this.sectionStates.chatHistory.expanded) {
                this.sectionStates.chatHistory.currentPage = 1;
                this.loadChatHistoryPage();
            } else {
                this.toggleSection('chatHistory');
            }
            this.showToast('聊天历史已刷新', 'success');
        }).catch(error => {
            console.error('刷新聊天历史失败:', error);
            this.showToast('刷新失败，请稍后重试', 'error');
        });
    }

    renderSidebarChatHistory(sessions) {
        const container = document.getElementById('sidebarHistoryList');
        container.innerHTML = '';

        if (sessions.length === 0) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-chat-dots fs-4 mb-2"></i>
                    <p>暂无对话历史</p>
                    <small>开始与AI角色对话后，历史记录将显示在这里</small>
                </div>
            `;
            return;
        }

        sessions.forEach(session => {
            const sessionElement = document.createElement('div');
            sessionElement.className = 'sidebar-history-item';
            sessionElement.innerHTML = `
                <div class="sidebar-history-content" onclick="app.loadSession('${session.sessionId}')">
                    <div class="sidebar-history-title">${session.sessionTitle}</div>
                    <div class="sidebar-history-meta">
                        角色: ${session.characterName} | 
                        消息数: ${session.messageCount} | 
                        最后活动: ${new Date(session.lastMessageAt).toLocaleString()}
                    </div>
                </div>
                <button class="sidebar-history-delete" onclick="app.deleteChatSession('${session.sessionId}', event)">
                    <i class="bi bi-trash"></i>
                </button>
            `;
            container.appendChild(sessionElement);
        });
    }

    async deleteChatSession(sessionId, event) {
        event.stopPropagation(); // 阻止事件冒泡
        
        if (!confirm('确定要删除这个对话记录吗？此操作不可恢复。')) {
            return;
        }
        
        try {
            const response = await this.fetchWithAuth(`/api/chat/sessions/${sessionId}`, {
                method: 'DELETE'
            });
            
            if (response.ok) {
                this.showToast('对话记录已删除', 'success');
                // 重新加载历史记录
                this.loadChatHistory();
            } else {
                this.showToast('删除失败', 'error');
            }
        } catch (error) {
            console.error('删除对话记录失败:', error);
            this.showToast('网络错误，请稍后再试', 'error');
        }
    }

    async loadSession(sessionId) {
        try {
            console.log('开始加载会话:', sessionId);
            
            // 先获取会话信息（包含角色ID）
            const sessionResponse = await this.fetchWithAuth(`/api/chat/session/${sessionId}`);
            if (!sessionResponse.ok) {
                console.error('获取会话信息失败，状态码:', sessionResponse.status);
                this.showToast('获取会话信息失败', 'error');
                return;
            }
            
            const sessionInfo = await sessionResponse.json();
            console.log('会话信息:', sessionInfo);
            
            if (!sessionInfo || !sessionInfo.characterId) {
                console.error('会话信息格式错误:', sessionInfo);
                this.showToast('会话信息格式错误', 'error');
                return;
            }
            
            // 获取聊天历史
            const historyResponse = await this.fetchWithAuth(`/api/chat/history/${sessionId}`);
            if (!historyResponse.ok) {
                console.error('获取聊天历史失败，状态码:', historyResponse.status);
                this.showToast('获取聊天历史失败', 'error');
                return;
            }
            
            const messages = await historyResponse.json();
            console.log('聊天历史:', messages);
            
            // 选择对应的角色并打开聊天界面
            await this.selectCharacter(sessionInfo.characterId);
            
            // 设置当前会话ID
            this.currentSession = sessionId;
            
            // 清空并重新加载消息
            document.getElementById('chatMessages').innerHTML = '';
            messages.forEach(message => {
                this.addMessage(message.messageType.toLowerCase(), message.content, message.skillUsed);
            });
            
            // 关闭侧边栏
            this.closeSidebar();
            
            console.log('会话加载完成');
            
        } catch (error) {
            console.error('加载会话失败:', error);
            this.showToast('加载会话失败: ' + error.message, 'error');
        }
    }

    showToast(message, type = 'info') {
        const toast = document.createElement('div');
        toast.className = `toast show position-fixed top-0 end-0 m-3`;
        toast.style.zIndex = '9999';
        
        const bgClass = {
            'success': 'bg-success text-white',
            'error': 'bg-danger text-white',
            'warning': 'bg-warning text-dark',
            'info': 'bg-info text-white'
        }[type] || 'bg-light';

        toast.innerHTML = `
            <div class="toast-body ${bgClass}">
                ${message}
            </div>
        `;
        
        document.body.appendChild(toast);
        setTimeout(() => toast.remove(), 3000);
    }

    // ========== 语音通话功能 ==========
    
    // 定时器管理函数
    addVoiceCallTimeout(callback, delay) {
        if (!this.isVoiceCallActive) {
            return null;
        }
        const timeoutId = setTimeout(() => {
            if (this.isVoiceCallActive) {
                callback();
            }
            // 从数组中移除已执行的定时器
            const index = this.voiceCallTimeouts.indexOf(timeoutId);
            if (index > -1) {
                this.voiceCallTimeouts.splice(index, 1);
            }
        }, delay);
        this.voiceCallTimeouts.push(timeoutId);
        return timeoutId;
    }
    
    clearAllVoiceCallTimeouts() {
        this.voiceCallTimeouts.forEach(timeoutId => {
            clearTimeout(timeoutId);
        });
        this.voiceCallTimeouts = [];
    }
    
    async startVoiceCall() {
        if (!this.currentCharacter) {
            this.showToast('请先选择一个角色开始对话', 'warning');
            return;
        }
        
        // 检查登录状态
        if (!this.token || !this.currentUser) {
            this.showToast('语音通话需要登录，请先登录', 'warning');
            // 显示登录模态框
            const loginModal = new bootstrap.Modal(document.getElementById('loginModal'));
            loginModal.show();
            return;
        }

        try {
            console.log('启动语音通话...');
            
            // 初始化语音通话界面
            this.initVoiceCallUI();
            
            // 请求麦克风权限
            await this.requestMicrophonePermission();
            
            // 显示语音通话模态框
            this.voiceCallModal = new bootstrap.Modal(document.getElementById('voiceCallModal'));
            this.voiceCallModal.show();
            
            // 设置通话状态
            this.isVoiceCallActive = true;
            this.updateCallStatus('语音通话已开始，请说话...');
            
            // 在设置通话状态后开始监听
            this.startVoiceListening();
            
            console.log('语音通话启动成功');
            
        } catch (error) {
            console.error('启动语音通话失败:', error);
            this.showToast('启动语音通话失败: ' + error.message, 'error');
        }
    }
    
    initVoiceCallUI() {
        // 设置角色信息
        const avatarElement = document.getElementById('voiceCallCharacterAvatar');
        const videoElement = document.getElementById('voiceCallCharacterVideo');
        const nameElement = document.getElementById('voiceCallCharacterName');
        
        if (this.currentCharacter) {
            // 定义有动态视频的角色映射
            const videoCharacterMap = {
                '哈利波特': 'halibote.mp4',
                '孔子': 'kongzi.mp4', 
                '苏格拉底': 'sugeladi.mp4',
                '艾丽莎博士': 'ailisha.mp4'
            };
            
            const videoFile = videoCharacterMap[this.currentCharacter.name];
            
            if (videoFile) {
                // 有动态视频的角色显示视频
                if (videoElement) {
                    videoElement.src = `mp4/${videoFile}`;
                    videoElement.style.display = 'block';
                    videoElement.load(); // 重新加载视频
                    console.log(`已设置${this.currentCharacter.name}动态头像视频:`, videoFile);
                }
                if (avatarElement) {
                    avatarElement.style.display = 'none';
                }
            } else {
                // 没有动态视频的角色显示静态头像
                if (avatarElement) {
                    avatarElement.style.display = 'flex';
                    // 尝试使用角色头像图片，如果没有则显示文字头像
                    if (this.currentCharacter.avatar_url) {
                        avatarElement.innerHTML = `<img src="${this.currentCharacter.avatar_url}" alt="${this.currentCharacter.name}" style="width: 100%; height: 100%; object-fit: cover; border-radius: inherit;">`;
                    } else {
                        avatarElement.textContent = this.currentCharacter.name.charAt(0);
                    }
                    console.log('已设置静态头像:', this.currentCharacter.name);
                }
                if (videoElement) {
                    videoElement.style.display = 'none';
                    videoElement.pause();
                }
            }
        }
        
        if (nameElement && this.currentCharacter) {
            nameElement.textContent = this.currentCharacter.name;
        }
        
        // 重置界面状态
        this.isTextDisplayMinimized = false;
        this.isMicrophoneMuted = false;
        this.currentAiResponse = '';
        
        // 重置按钮状态
        this.updateMicrophoneButton();
        this.updateTextDisplayButton();
        
        // 隐藏最小化控制，显示正常控制
        document.getElementById('minimizedControls').classList.add('hidden');
        document.getElementById('voiceCallControls').classList.remove('hidden');
        document.getElementById('voiceWaveContainer').classList.remove('hidden');
        document.getElementById('aiResponseText').classList.add('hidden');
    }
    
    async requestMicrophonePermission() {
        try {
            this.voiceCallStream = await navigator.mediaDevices.getUserMedia({
                audio: {
                    sampleRate: 16000,
                    channelCount: 1,
                    echoCancellation: true,
                    noiseSuppression: true,
                    autoGainControl: true
                }
            });
            
            console.log('麦克风权限获取成功');
            
            // 初始化语音识别
            this.initVoiceRecognition();
            
        } catch (error) {
            console.error('获取麦克风权限失败:', error);
            throw new Error('无法访问麦克风，请检查权限设置');
        }
    }
    
    initVoiceRecognition() {
        if (!this.voiceCallStream) return;
        
        try {
            // 创建媒体录制器
            this.voiceCallRecorder = new MediaRecorder(this.voiceCallStream, {
                mimeType: 'audio/webm;codecs=opus'
            });
            
            let audioChunks = [];
            
            this.voiceCallRecorder.ondataavailable = (event) => {
                if (event.data.size > 0) {
                    audioChunks.push(event.data);
                }
            };
            
            this.voiceCallRecorder.onstop = async () => {
                if (audioChunks.length > 0) {
                    const rawBlob = new Blob(audioChunks, { type: 'audio/webm' });
                    audioChunks = [];
                    
                    console.log('语音通话录音完成(原始):', {
                        size: rawBlob.size,
                        type: rawBlob.type
                    });
                    
                    // 转换为16k单声道WAV，提升ASR识别效果（与普通对话保持一致）
                    let wavBlob;
                    try {
                        wavBlob = await this.convertTo16kMonoWav(rawBlob);
                        console.log('语音通话转换完成(WAV 16k mono):', { 
                            size: wavBlob.size, 
                            type: wavBlob.type 
                        });
                    } catch (e) {
                        console.warn('语音通话音频转换为WAV失败，回退上传原始格式:', e);
                        wavBlob = rawBlob;
                    }
                    
                    // 发送转换后的音频进行识别
                    await this.processVoiceInput(wavBlob);
                }
            };
            
            // 注意：语音监听将在startVoiceCall中设置isVoiceCallActive后开始
            
        } catch (error) {
            console.error('初始化语音识别失败:', error);
            this.showToast('语音识别初始化失败', 'error');
        }
    }
    
    startVoiceListening() {
        // 如果语音通话未激活，不允许开始监听
        if (!this.isVoiceCallActive) {
            console.log('语音通话未激活，停止监听');
            return;
        }
        
        // 如果AI正在说话或正在处理语音输入，不允许开始新的监听
        if (!this.voiceCallRecorder || this.isMicrophoneMuted || this.isAiSpeaking || this.isProcessingVoiceInput) {
            console.log('无法开始监听:', {
                hasRecorder: !!this.voiceCallRecorder,
                isMuted: this.isMicrophoneMuted,
                isAiSpeaking: this.isAiSpeaking,
                isProcessing: this.isProcessingVoiceInput
            });
            return;
        }
        
        // 开始录制
        this.voiceCallRecorder.start();
        
        // 显示说话状态
        this.updateCallStatus('正在聆听...');
        const voiceCallModal = document.querySelector('.voice-call-modal');
        if (voiceCallModal) {
            voiceCallModal.classList.add('listening');
        }
        
        // 设置录制超时（比如5秒后自动停止）
        this.addVoiceCallTimeout(() => {
            if (this.voiceCallRecorder && this.voiceCallRecorder.state === 'recording') {
                this.voiceCallRecorder.stop();
                
                // 等待一段时间后重新开始监听
                this.addVoiceCallTimeout(() => {
                    this.startVoiceListening();
                }, 1000);
            }
        }, 5000);
    }
    
    async processVoiceInput(audioBlob) {
        try {
            // 设置处理状态，防止多个问题同时进入
            this.isProcessingVoiceInput = true;
            this.updateCallStatus('正在识别语音...');
            
            // 创建FormData发送音频
            const formData = new FormData();
            const fileName = (audioBlob && audioBlob.type && audioBlob.type.includes('wav')) ? 'voice_call.wav' : 'voice_call.webm';
            formData.append('audio', audioBlob, fileName);
            
            console.log('语音通话发送音频:', {
                fileName: fileName,
                size: audioBlob.size,
                type: audioBlob.type
            });
            
            // 使用语音通话专用的ASR端点
            const headers = {};
            if (this.token) {
                headers['Authorization'] = `Bearer ${this.token}`;
            }
            
            // 添加策略参数
            if (this.selectedStrategy) {
                formData.append('strategy', this.selectedStrategy);
            }
            
            const response = await fetch('/api/voice/voice-call/asr', {
                method: 'POST',
                headers: headers,
                body: formData
            });
            
            if (response.ok) {
                const result = await response.json();
                if (result.success && result.text && result.text.trim()) {
                    console.log('语音识别成功:', result.text);
                    
                    // 更新状态显示识别结果
                    this.updateCallStatus(`识别到: "${result.text}"`);
                    
                    // 在聊天界面中添加用户语音消息
                    this.addMessage('user', result.text, null, null, true); // 标记为语音消息
                    
                    // 重置处理状态
                    this.isProcessingVoiceInput = false;
                    
                    // 短暂显示识别结果后发送给GLM
                    this.addVoiceCallTimeout(async () => {
                        await this.sendVoiceCallMessage(result.text);
                    }, 1000);
                    
                } else {
                    console.warn('语音识别失败:', result);
                    this.updateCallStatus('语音识别失败，请重试');
                    
                    // 重置处理状态
                    this.isProcessingVoiceInput = false;
                    
                    // 重新开始监听
                    this.addVoiceCallTimeout(() => {
                        this.startVoiceListening();
                    }, 2000);
                }
            } else {
                console.error('语音识别请求失败:', response.status);
                this.updateCallStatus('语音识别失败，请重试');
                
                // 重置处理状态
                this.isProcessingVoiceInput = false;
                
                // 重新开始监听
                setTimeout(() => {
                    this.startVoiceListening();
                }, 2000);
            }
            
        } catch (error) {
            console.error('处理语音输入失败:', error);
            this.updateCallStatus('语音识别失败，请重试');
            
            // 重置处理状态
            this.isProcessingVoiceInput = false;
            
            // 重新开始监听
            this.addVoiceCallTimeout(() => {
                this.startVoiceListening();
            }, 2000);
        }
    }
    
    async sendVoiceCallMessage(text) {
        try {
            this.updateCallStatus('AI正在思考...');
            
            const chatRequest = {
                characterId: this.currentCharacter.id,
                message: text,
                sessionId: this.currentSession,
                preferredSkill: 'memory' // 默认使用记忆技能
            };
            
            console.log('发送给GLM的消息:', text);
            console.log('聊天请求参数:', chatRequest);
            
            const response = await this.fetchWithAuth('/api/chat/send', {
                method: 'POST',
                body: JSON.stringify(chatRequest)
            });
            
            if (response.ok) {
                const result = await response.json();
                if (result.success && result.message) {
                    console.log('GLM回复成功:', result.message);
                    console.log('使用的技能:', result.skillUsed);
                    console.log('检测到的情感:', result.emotionDetected);
                    
                    // 保存AI回复
                    this.currentAiResponse = result.message;
                    
                    // 更新会话ID
                    if (result.sessionId) {
                        this.currentSession = result.sessionId;
                    }
                    
                    // 在聊天界面中添加AI回复消息
                    this.addMessage('assistant', result.message, result.skillUsed, result.audioUrl, true); // 标记为语音消息
                    
                    // 显示AI正在说话状态
                    this.updateCallStatus('AI正在回复...');
                    const voiceCallModal = document.querySelector('.voice-call-modal');
                    if (voiceCallModal) {
                        voiceCallModal.classList.add('speaking');
                    }
                    
                    // 播放AI回复语音
                    await this.playAiVoiceResponse(result.message);
                    
                    // 如果显示文字模式，更新文字内容
                    if (this.isTextDisplayMinimized) {
                        document.getElementById('responseContent').textContent = result.message;
                    }
                    
                } else {
                    console.warn('GLM回复失败:', result);
                    this.updateCallStatus('AI回复失败，请重试');
                    
                    // 重置处理状态
                    this.isProcessingVoiceInput = false;
                    
                    // 重新开始监听
                    this.addVoiceCallTimeout(() => {
                        this.startVoiceListening();
                    }, 2000);
                }
            } else {
                console.error('GLM请求失败:', response.status);
                this.updateCallStatus('AI服务暂时不可用，请重试');
                
                // 重置处理状态
                this.isProcessingVoiceInput = false;
                
                // 重新开始监听
                setTimeout(() => {
                    this.startVoiceListening();
                }, 2000);
            }
            
        } catch (error) {
            console.error('发送语音消息失败:', error);
            this.updateCallStatus('发送消息失败，请重试');
            
            // 重置处理状态
            this.isProcessingVoiceInput = false;
            
            // 重新开始监听
            this.addVoiceCallTimeout(() => {
                this.startVoiceListening();
            }, 2000);
        }
    }
    
    async playAiVoiceResponse(text) {
        try {
            // 设置AI说话状态
            this.isAiSpeaking = true;
            this.currentAudio = null;
            
            // 显示打断按钮
            this.showInterruptButton();
            
            // 生成TTS
            const response = await this.fetchWithAuth('/api/voice/tts', {
                method: 'POST',
                body: JSON.stringify({
                    text: text,
                    characterName: this.currentCharacter.name
                })
            });
            
            if (response.ok) {
                const result = await response.json();
                if (result.success && result.audioUrl) {
                    // 播放音频
                    const audio = new Audio(result.audioUrl);
                    this.currentAudio = audio;
                    
                    audio.onended = () => {
                        // 播放结束，恢复监听状态
                        this.onAiSpeakingEnd();
                    };
                    
                    audio.onerror = () => {
                        console.error('音频播放失败');
                        this.onAiSpeakingEnd();
                    };
                    
                    await audio.play();
                } else {
                    this.onAiSpeakingEnd();
                }
            } else {
                this.onAiSpeakingEnd();
            }
            
        } catch (error) {
            console.error('播放AI语音回复失败:', error);
            this.onAiSpeakingEnd();
        }
    }
    
    toggleMicrophone() {
        this.isMicrophoneMuted = !this.isMicrophoneMuted;
        
        if (this.isMicrophoneMuted) {
            // 静音麦克风
            if (this.voiceCallRecorder && this.voiceCallRecorder.state === 'recording') {
                this.voiceCallRecorder.stop();
            }
            if (this.voiceCallStream) {
                this.voiceCallStream.getAudioTracks().forEach(track => {
                    track.enabled = false;
                });
            }
            this.updateCallStatus('麦克风已静音');
        } else {
            // 开启麦克风
            if (this.voiceCallStream) {
                this.voiceCallStream.getAudioTracks().forEach(track => {
                    track.enabled = true;
                });
            }
            this.updateCallStatus('请继续说话...');
            this.startVoiceListening();
        }
        
        this.updateMicrophoneButton();
    }
    
    updateMicrophoneButton() {
        const micBtn = document.getElementById('micBtn');
        const micBtnMini = document.querySelector('.mic-btn-mini');
        
        if (micBtn) {
            micBtn.classList.remove('active', 'muted');
            const icon = micBtn.querySelector('i');
            
            if (this.isMicrophoneMuted) {
                micBtn.classList.add('muted');
                icon.className = 'bi bi-mic-mute';
            } else {
                micBtn.classList.add('active');
                icon.className = 'bi bi-mic';
            }
        }
        
        if (micBtnMini) {
            micBtnMini.classList.remove('active', 'muted');
            const icon = micBtnMini.querySelector('i');
            
            if (this.isMicrophoneMuted) {
                micBtnMini.classList.add('muted');
                icon.className = 'bi bi-mic-mute';
            } else {
                micBtnMini.classList.add('active');
                icon.className = 'bi bi-mic';
            }
        }
    }
    
    toggleTextDisplay() {
        this.isTextDisplayMinimized = !this.isTextDisplayMinimized;
        
        if (this.isTextDisplayMinimized) {
            // 切换到最小化模式，显示文字
            document.getElementById('voiceCallControls').classList.add('hidden');
            document.getElementById('voiceWaveContainer').classList.add('hidden');
            document.getElementById('aiResponseText').classList.remove('hidden');
            document.getElementById('minimizedControls').classList.remove('hidden');
            
            // 更新文字内容
            document.getElementById('responseContent').textContent = this.currentAiResponse || '暂无AI回复';
            
        } else {
            // 切换回正常模式
            document.getElementById('voiceCallControls').classList.remove('hidden');
            document.getElementById('voiceWaveContainer').classList.remove('hidden');
            document.getElementById('aiResponseText').classList.add('hidden');
            document.getElementById('minimizedControls').classList.add('hidden');
        }
        
        this.updateTextDisplayButton();
    }
    
    updateTextDisplayButton() {
        const textBtn = document.getElementById('textBtn');
        const textBtnMini = document.querySelector('.text-btn-mini');
        
        if (textBtn) {
            if (this.isTextDisplayMinimized) {
                textBtn.classList.add('active');
            } else {
                textBtn.classList.remove('active');
            }
        }
        
        if (textBtnMini) {
            if (this.isTextDisplayMinimized) {
                textBtnMini.classList.add('active');
            } else {
                textBtnMini.classList.remove('active');
            }
        }
    }
    
    async copyAiResponse() {
        if (!this.currentAiResponse) {
            this.showToast('暂无可复制的内容', 'warning');
            return;
        }
        
        try {
            await navigator.clipboard.writeText(this.currentAiResponse);
            this.showToast('AI回复已复制到剪贴板', 'success');
        } catch (error) {
            console.error('复制失败:', error);
            this.showToast('复制失败，请手动复制', 'error');
        }
    }
    
    endVoiceCall() {
        console.log('结束语音通话...');
        
        // 停止录制
        if (this.voiceCallRecorder && this.voiceCallRecorder.state === 'recording') {
            this.voiceCallRecorder.stop();
        }
        
        // 关闭媒体流
        if (this.voiceCallStream) {
            this.voiceCallStream.getTracks().forEach(track => {
                track.stop();
            });
            this.voiceCallStream = null;
        }
        
        // 清除所有语音通话相关的定时器
        this.clearAllVoiceCallTimeouts();
        
        // 停止当前播放的音频
        if (this.currentAudio && !this.currentAudio.paused) {
            this.currentAudio.pause();
            this.currentAudio.currentTime = 0; // 重置播放位置
            console.log('语音通话结束，已暂停正在播放的音频');
        }
        
        // 如果AI正在说话，也要停止
        if (this.isAiSpeaking) {
            this.isAiSpeaking = false;
            this.hideInterruptButton();
            document.querySelector('.voice-call-modal')?.classList.remove('speaking');
            console.log('语音通话结束，已停止AI说话状态');
        }
        
        // 重置状态
        this.isVoiceCallActive = false;
        this.voiceCallRecorder = null;
        this.isMicrophoneMuted = false;
        this.isTextDisplayMinimized = false;
        this.currentAiResponse = '';
        this.isAiSpeaking = false;
        this.isProcessingVoiceInput = false;
        this.currentAudio = null;
        
        // 停止视频播放
        const videoElement = document.getElementById('voiceCallCharacterVideo');
        if (videoElement) {
            videoElement.pause();
            videoElement.style.display = 'none';
        }
        
        // 关闭模态框
        if (this.voiceCallModal) {
            this.voiceCallModal.hide();
            this.voiceCallModal = null;
        }
        
        // 清除状态类
        const modal = document.querySelector('.voice-call-modal');
        if (modal) {
            modal.classList.remove('listening', 'speaking');
        }
        
        // 隐藏打断按钮
        this.hideInterruptButton();
        
        console.log('语音通话已结束');
    }
    
    updateCallStatus(status) {
        const statusElement = document.getElementById('callStatus');
        if (statusElement) {
            statusElement.textContent = status;
        }
    }
    
    // ========== 打断功能相关方法 ==========
    
    showInterruptButton() {
        const interruptSection = document.getElementById('interruptSection');
        if (interruptSection) {
            interruptSection.classList.remove('hidden');
        }
    }
    
    hideInterruptButton() {
        const interruptSection = document.getElementById('interruptSection');
        if (interruptSection) {
            interruptSection.classList.add('hidden');
        }
    }
    
    interruptAiResponse() {
        console.log('用户打断AI回答');
        
        // 停止当前音频播放
        if (this.currentAudio) {
            this.currentAudio.pause();
            this.currentAudio.currentTime = 0;
            this.currentAudio = null;
        }
        
        // 重置AI说话状态
        this.isAiSpeaking = false;
        
        // 隐藏打断按钮
        this.hideInterruptButton();
        
        // 清除说话状态类
        const voiceCallModal = document.querySelector('.voice-call-modal');
        if (voiceCallModal) {
            voiceCallModal.classList.remove('speaking');
        }
        
        // 更新状态
        this.updateCallStatus('已打断AI回答，请继续说话...');
        
        // 重置处理状态
        this.isProcessingVoiceInput = false;
        
        // 重新开始监听
        this.addVoiceCallTimeout(() => {
            this.startVoiceListening();
        }, 1000);
        
        this.showToast('已打断AI回答', 'info');
    }
    
    onAiSpeakingEnd() {
        // 重置AI说话状态
        this.isAiSpeaking = false;
        this.currentAudio = null;
        
        // 隐藏打断按钮
        this.hideInterruptButton();
        
        // 清除说话状态类
        const voiceCallModal = document.querySelector('.voice-call-modal');
        if (voiceCallModal) {
            voiceCallModal.classList.remove('speaking');
        }
        
        // 更新状态
        this.updateCallStatus('请继续说话...');
        
        // 重置处理状态
        this.isProcessingVoiceInput = false;
        
        // 重新开始监听
        this.addVoiceCallTimeout(() => {
            this.startVoiceListening();
        }, 1000);
    }

    // ========== 侧边栏相关方法 ==========
    
    toggleSidebar() {
        const sidebar = document.getElementById('sidebar');
        const overlay = document.getElementById('sidebarOverlay');
        
        if (sidebar.classList.contains('open')) {
            this.closeSidebar();
        } else {
            this.openSidebar();
        }
    }
    
    openSidebar() {
        const sidebar = document.getElementById('sidebar');
        const overlay = document.getElementById('sidebarOverlay');
        
        sidebar.classList.add('open');
        overlay.classList.add('show');
        
        // 加载对话历史
        this.loadChatHistory();
        
        // 加载搜索历史
        this.loadSearchHistory();
    }
    
    closeSidebar() {
        const sidebar = document.getElementById('sidebar');
        const overlay = document.getElementById('sidebarOverlay');
        
        sidebar.classList.remove('open');
        overlay.classList.remove('show');
    }

    // 搜索历史相关功能
    addToSearchHistory(searchTerm) {
        if (!searchTerm || searchTerm.trim() === '') return;
        
        const term = searchTerm.trim();
        console.log('添加搜索历史:', term);
        
        // 移除重复项
        this.searchHistory = this.searchHistory.filter(item => item !== term);
        
        // 添加到开头
        this.searchHistory.unshift(term);
        
        // 限制数量
        if (this.searchHistory.length > this.maxSearchHistory) {
            this.searchHistory = this.searchHistory.slice(0, this.maxSearchHistory);
        }
        
        // 保存到本地存储
        localStorage.setItem('searchHistory', JSON.stringify(this.searchHistory));
        
        // 更新缓存
        this.setCacheData('searchHistory', this.searchHistory);
        
        console.log('搜索历史已保存:', this.searchHistory);
        
        // 更新显示
        this.loadSearchHistory();
        this.updateSearchHistoryHorizontal();
    }

    loadSearchHistory() {
        const container = document.getElementById('searchHistoryList');
        if (!container) return;
        
        // 从缓存加载搜索历史
        const cachedHistory = this.getCacheData('searchHistory');
        if (cachedHistory) {
            this.searchHistory = cachedHistory;
        }
        
        container.innerHTML = '';
        
        if (this.searchHistory.length === 0) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-search fs-4 mb-2"></i>
                    <p>暂无搜索记录</p>
                    <small>搜索后记录将显示在这里</small>
                </div>
            `;
            return;
        }
        
        this.searchHistory.forEach((term, index) => {
            const itemElement = document.createElement('div');
            itemElement.className = 'search-history-item';
            itemElement.innerHTML = `
                <span class="search-history-text" onclick="app.selectSearchHistory('${term}')">${term}</span>
                <button class="search-history-delete" onclick="app.deleteSearchHistory(${index}, event)">
                    <i class="bi bi-x"></i>
                </button>
            `;
            container.appendChild(itemElement);
        });
    }

    deleteSearchHistory(index, event) {
        event.stopPropagation();
        
        this.searchHistory.splice(index, 1);
        localStorage.setItem('searchHistory', JSON.stringify(this.searchHistory));
        
        this.loadSearchHistory();
        this.updateSearchHistoryHorizontal();
        
        this.showToast('搜索记录已删除', 'success');
    }

    // 从横向显示中删除搜索历史
    deleteSearchHistoryFromHorizontal(index, event) {
        event.stopPropagation();
        event.preventDefault();
        
        console.log('删除搜索历史，索引:', index, '当前历史记录:', this.searchHistory);
        
        // 由于横向显示只显示前10条，需要确保删除的是正确的索引
        if (index >= 0 && index < this.searchHistory.length) {
            const deletedTerm = this.searchHistory[index];
            this.searchHistory.splice(index, 1);
            localStorage.setItem('searchHistory', JSON.stringify(this.searchHistory));
            
            // 更新缓存
            this.setCacheData('searchHistory', this.searchHistory);
            
            // 更新显示
            this.loadSearchHistory();
            this.updateSearchHistoryHorizontal();
            
            console.log('删除成功，删除的项:', deletedTerm, '剩余历史记录:', this.searchHistory);
            this.showToast('搜索记录已删除', 'success');
        } else {
            console.error('删除失败，索引超出范围:', index, '历史记录长度:', this.searchHistory.length);
        }
    }

    clearSearchHistory(event = null) {
        if (event) {
            event.stopPropagation();
        }
        
        if (this.searchHistory.length === 0) {
            this.showToast('没有搜索记录可清除', 'info');
            return;
        }
        
        if (confirm('确定要清除所有搜索记录吗？')) {
            this.searchHistory = [];
            localStorage.setItem('searchHistory', JSON.stringify(this.searchHistory));
            
            // 清除缓存
            this.clearCache('searchHistory');
            
            // 如果搜索历史栏是展开的，重新加载
            if (this.sectionStates.searchHistory.expanded) {
                this.loadSearchHistoryPage();
            }
            
            this.updateSearchHistoryHorizontal();
            
            this.showToast('搜索记录已清除', 'success');
        }
    }

    selectSearchHistory(term) {
        // 设置搜索框的值
        const searchInput = document.getElementById('searchInput');
        if (searchInput) {
            searchInput.value = term;
            this.closeAllSearchDropdowns();
            this.searchCharacters(term, false); // 不保存到历史记录，因为已经在历史记录中了
        }
    }


    // 更新横向显示的搜索历史
    updateSearchHistoryHorizontal() {
        const container = document.getElementById('searchHistoryItems');
        if (!container) return;
        
        if (this.searchHistory.length === 0) {
            container.innerHTML = `
                <div class="search-history-empty">
                    <i class="bi bi-clock-history"></i>
                    <span>暂无搜索记录</span>
                </div>
            `;
            return;
        }
        
        // 显示所有搜索记录（最多10条）
        const maxItems = Math.min(this.searchHistory.length, 10);
        container.innerHTML = this.searchHistory.slice(0, maxItems).map((term, index) => `
            <div class="search-history-item-horizontal" onclick="app.selectSearchHistory('${term}')">
                <span class="search-history-text-horizontal">${term}</span>
                <button class="search-history-delete-horizontal" onclick="app.deleteSearchHistoryFromHorizontal(${index}, event)" title="删除">
                    <i class="bi bi-x"></i>
                </button>
            </div>
        `).join('');
    }

    setupSearchListeners() {
        // 点击页面其他地方隐藏所有下拉框
        document.addEventListener('click', (e) => {
            const searchContainer = document.querySelector('.search-container');
            if (searchContainer && !searchContainer.contains(e.target)) {
                this.closeAllSearchDropdowns();
            }
        });
    }

    // 侧边栏展开/收起功能
    toggleSection(sectionName) {
        const state = this.sectionStates[sectionName];
        const header = document.querySelector(`[onclick="app.toggleSection('${sectionName}')"]`);
        const contentList = document.getElementById(this.getContentListId(sectionName));
        const pagination = document.getElementById(this.getPaginationId(sectionName));
        
        if (!state.expanded) {
            // 展开
            state.expanded = true;
            state.currentPage = 1;
            header.classList.add('expanded');
            contentList.style.display = 'block';
            
            // 加载第一页数据
            this.loadSectionData(sectionName);
        } else {
            // 收起
            state.expanded = false;
            header.classList.remove('expanded');
            contentList.style.display = 'none';
            if (pagination) {
                pagination.style.display = 'none';
            }
        }
    }

    getContentListId(sectionName) {
        const mapping = {
            'searchHistory': 'searchHistoryList',
            'allCharacters': 'allCharactersList',
            'chatHistory': 'sidebarHistoryList'
        };
        return mapping[sectionName];
    }

    getPaginationId(sectionName) {
        const mapping = {
            'searchHistory': 'searchHistoryPagination',
            'allCharacters': 'allCharactersPagination',
            'chatHistory': 'chatHistoryPagination'
        };
        return mapping[sectionName];
    }

    loadSectionData(sectionName) {
        switch (sectionName) {
            case 'searchHistory':
                this.loadSearchHistoryPage();
                break;
            case 'allCharacters':
                this.loadAllCharactersPage();
                break;
            case 'chatHistory':
                this.loadChatHistoryPage();
                break;
        }
    }

    // 搜索历史分页
    loadSearchHistoryPage() {
        const container = document.getElementById('searchHistoryList');
        const pagination = document.getElementById('searchHistoryPagination');
        const state = this.sectionStates.searchHistory;
        
        container.innerHTML = '';
        
        if (this.searchHistory.length === 0) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-search fs-4 mb-2"></i>
                    <p>暂无搜索记录</p>
                    <small>搜索后记录将显示在这里</small>
                </div>
            `;
            pagination.style.display = 'none';
            return;
        }
        
        const startIndex = (state.currentPage - 1) * this.itemsPerPage;
        const endIndex = Math.min(startIndex + this.itemsPerPage, this.searchHistory.length);
        const currentPageItems = this.searchHistory.slice(startIndex, endIndex);
        
        currentPageItems.forEach((term, index) => {
            const itemElement = document.createElement('div');
            itemElement.className = 'search-history-item';
            itemElement.innerHTML = `
                <span class="search-history-text" onclick="app.selectSearchHistory('${term}')">${term}</span>
                <button class="search-history-delete" onclick="app.deleteSearchHistory(${startIndex + index}, event)">
                    <i class="bi bi-x"></i>
                </button>
            `;
            container.appendChild(itemElement);
        });
        
        // 显示/隐藏分页按钮
        if (endIndex < this.searchHistory.length) {
            pagination.style.display = 'block';
        } else {
            pagination.style.display = 'none';
        }
    }

    loadMoreSearchHistory() {
        this.sectionStates.searchHistory.currentPage++;
        this.loadSearchHistoryPage();
    }

    // 全部人物分页
    async loadAllCharactersPage() {
        const container = document.getElementById('allCharactersList');
        const pagination = document.getElementById('allCharactersPagination');
        const state = this.sectionStates.allCharacters;
        
        // 首先尝试从缓存加载
        let characters = this.getCacheData('characters');
        
        if (characters && characters.length > 0) {
            console.log('从缓存加载角色数据用于侧边栏显示');
            this.renderSidebarCharacters(container, pagination, characters, state);
            return;
        }
        
        // 如果缓存中没有数据，显示加载状态并请求后端
        container.innerHTML = `
            <div class="text-center text-muted py-3">
                <i class="bi bi-hourglass-split fs-4 mb-2"></i>
                <p>加载中...</p>
                <small>正在获取人物列表</small>
            </div>
        `;
        
        try {
            const response = await fetch('/api/characters');
            if (response.ok) {
                characters = await response.json();
                
                // 缓存数据
                this.setCacheData('characters', characters);
                
                this.renderSidebarCharacters(container, pagination, characters, state);
            } else {
                container.innerHTML = `
                    <div class="text-center text-muted py-3">
                        <i class="bi bi-exclamation-triangle fs-4 mb-2"></i>
                        <p>加载失败</p>
                        <small>无法获取人物列表</small>
                    </div>
                `;
            }
        } catch (error) {
            console.error('加载人物列表失败:', error);
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-exclamation-triangle fs-4 mb-2"></i>
                    <p>网络错误</p>
                    <small>请检查网络连接</small>
                </div>
            `;
        }
    }
    
    /**
     * 渲染侧边栏角色列表
     */
    renderSidebarCharacters(container, pagination, characters, state) {
        container.innerHTML = '';
        
        if (characters.length === 0) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-grid-3x3-gap fs-4 mb-2"></i>
                    <p>暂无人物</p>
                    <small>系统中还没有配置任何人物</small>
                </div>
            `;
            pagination.style.display = 'none';
            return;
        }
        
        const startIndex = (state.currentPage - 1) * this.itemsPerPage;
        const endIndex = Math.min(startIndex + this.itemsPerPage, characters.length);
        const currentPageItems = characters.slice(startIndex, endIndex);
        
        currentPageItems.forEach(character => {
            const itemElement = document.createElement('div');
            itemElement.className = 'sidebar-character-item';
            itemElement.onclick = () => this.selectCharacter(character.id);
            itemElement.innerHTML = `
                <div class="sidebar-character-avatar">
                    <img src="${character.avatarUrl || '/images/img.png'}" alt="${character.name}" onerror="this.src='/images/img.png'">
                </div>
                <div class="sidebar-character-info">
                    <div class="sidebar-character-name">${character.name}</div>
                    <div class="sidebar-character-desc">${character.description || '暂无描述'}</div>
                </div>
            `;
            container.appendChild(itemElement);
        });
        
        // 显示/隐藏分页按钮
        if (endIndex < characters.length) {
            pagination.style.display = 'block';
        } else {
            pagination.style.display = 'none';
        }
    }

    loadMoreAllCharacters() {
        this.sectionStates.allCharacters.currentPage++;
        this.loadAllCharactersPage();
    }

    // 对话历史分页
    async loadChatHistoryPage() {
        const container = document.getElementById('sidebarHistoryList');
        const pagination = document.getElementById('chatHistoryPagination');
        const state = this.sectionStates.chatHistory;
        
        if (!this.currentUser) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-person-x fs-4 mb-2"></i>
                    <p>请先登录</p>
                    <small>登录后查看对话历史</small>
                </div>
            `;
            pagination.style.display = 'none';
            return;
        }
        
        // 首先尝试从缓存加载
        let sessions = this.getCacheData('chatHistory');
        
        if (sessions && sessions.length >= 0) {
            console.log('从缓存加载聊天历史数据');
            this.renderSidebarChatHistory(container, pagination, sessions, state);
            return;
        }
        
        try {
            const response = await this.fetchWithAuth('/api/chat/my-sessions');
            if (response.ok) {
                sessions = await response.json();
                
                // 缓存数据
                this.setCacheData('chatHistory', sessions);
                
                this.renderSidebarChatHistory(container, pagination, sessions, state);
            } else {
                container.innerHTML = `
                    <div class="text-center text-muted py-3">
                        <i class="bi bi-exclamation-triangle fs-4 mb-2"></i>
                        <p>加载失败</p>
                        <small>无法获取对话历史</small>
                    </div>
                `;
            }
        } catch (error) {
            console.error('加载对话历史失败:', error);
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-exclamation-triangle fs-4 mb-2"></i>
                    <p>网络错误</p>
                    <small>请检查网络连接</small>
                </div>
            `;
        }
    }
    
    /**
     * 渲染侧边栏聊天历史
     */
    renderSidebarChatHistory(container, pagination, sessions, state) {
        container.innerHTML = '';
        
        if (sessions.length === 0) {
            container.innerHTML = `
                <div class="text-center text-muted py-3">
                    <i class="bi bi-chat-dots fs-4 mb-2"></i>
                    <p>暂无对话历史</p>
                    <small>开始与AI角色对话后，历史记录将显示在这里</small>
                </div>
            `;
            pagination.style.display = 'none';
            return;
        }
        
        const startIndex = (state.currentPage - 1) * this.itemsPerPage;
        const endIndex = Math.min(startIndex + this.itemsPerPage, sessions.length);
        const currentPageItems = sessions.slice(startIndex, endIndex);
        
        currentPageItems.forEach(session => {
            const sessionElement = document.createElement('div');
            sessionElement.className = 'sidebar-history-item';
            sessionElement.innerHTML = `
                <div class="sidebar-history-content" onclick="app.loadSession('${session.sessionId}')">
                    <div class="sidebar-history-title">${session.sessionTitle}</div>
                    <div class="sidebar-history-meta">
                        角色: ${session.characterName} | 
                        消息数: ${session.messageCount} | 
                        最后活动: ${new Date(session.lastMessageAt).toLocaleString()}
                    </div>
                </div>
                <button class="sidebar-history-delete" onclick="app.deleteChatSession('${session.sessionId}', event)">
                    <i class="bi bi-trash"></i>
                </button>
            `;
            container.appendChild(sessionElement);
        });
        
        // 显示/隐藏分页按钮
        if (endIndex < sessions.length) {
            pagination.style.display = 'block';
        } else {
            pagination.style.display = 'none';
        }
    }

    loadMoreChatHistory() {
        this.sectionStates.chatHistory.currentPage++;
        this.loadChatHistoryPage();
    }

    refreshAllCharacters(event = null) {
        if (event) {
            event.stopPropagation();
        }
        
        // 强制刷新角色数据
        this.forceRefreshData('characters').then(() => {
            // 如果全部人物栏是展开的，重新加载
            if (this.sectionStates.allCharacters.expanded) {
                this.sectionStates.allCharacters.currentPage = 1;
                this.loadAllCharactersPage();
            } else {
                // 如果未展开，先展开再加载
                this.toggleSection('allCharacters');
            }
            this.showToast('角色数据已刷新', 'success');
        }).catch(error => {
            console.error('刷新角色数据失败:', error);
            this.showToast('刷新失败，请稍后重试', 'error');
        });
    }
    
    toggleAllCharacters() {
        const characterList = document.getElementById('characterList');
        
        this.isAllCharactersVisible = !this.isAllCharactersVisible;
        
        if (this.isAllCharactersVisible) {
            // 显示全部人物卡片
            characterList.classList.remove('hidden');
            
            // 如果还没有加载人物数据，则加载
            if (this.displayedCharacters.length === 0) {
                this.refreshCharacters();
            }
        } else {
            // 隐藏全部人物卡片
            characterList.classList.add('hidden');
        }
    }
    
    // 模型管理相关方法
    async loadAvailableModels() {
        try {
            const response = await fetch('/api/model/available');
            const data = await response.json();
            
            if (data.success) {
                this.availableModels = data.models;
                this.renderModelList();
                this.updateCurrentModelDisplay();
            } else {
                console.error('加载模型列表失败:', data.message);
            }
        } catch (error) {
            console.error('加载模型列表异常:', error);
        }
    }
    
    async getCurrentModel() {
        try {
            const response = await fetch('/api/model/current');
            const data = await response.json();
            
            if (data.success) {
                this.currentModel = data.modelName;
                this.updateCurrentModelDisplay();
            }
        } catch (error) {
            console.error('获取当前模型异常:', error);
        }
    }
    
    async switchModel(modelName) {
        try {
            const response = await fetch('/api/model/switch', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ modelName: modelName })
            });
            
            const data = await response.json();
            
            if (data.success) {
                this.currentModel = data.currentModel;
                this.updateCurrentModelDisplay();
                this.renderModelList();
                this.closeModelDropdown();
                
                // 显示成功提示
                this.showToast('模型切换成功', 'success');
            } else {
                this.showToast(data.message || '模型切换失败', 'error');
            }
        } catch (error) {
            console.error('切换模型异常:', error);
            this.showToast('模型切换异常', 'error');
        }
    }
    
    closeModelDropdown() {
        const dropdown = document.getElementById('modelDropdown');
        if (dropdown) {
            dropdown.classList.remove('show');
        }
    }
    
    renderModelList() {
        const modelList = document.getElementById('modelList');
        if (!modelList) return;
        
        modelList.innerHTML = '';
        
        this.availableModels.forEach(model => {
            const modelItem = document.createElement('div');
            modelItem.className = `model-item ${model.isCurrent ? 'current' : ''}`;
            modelItem.onclick = () => this.switchModel(model.modelName);
            
            modelItem.innerHTML = `
                <div class="model-item-icon">
                    <i class="bi bi-cpu"></i>
                </div>
                <div class="model-item-info">
                    <div class="model-item-name">${model.displayName}</div>
                    <div class="model-item-description">${model.description}</div>
                </div>
                ${model.isCurrent ? '<div class="model-item-status">当前</div>' : ''}
            `;
            
            modelList.appendChild(modelItem);
        });
    }
    
    updateCurrentModelDisplay() {
        const currentModelDisplay = document.getElementById('currentModelDisplay');
        if (currentModelDisplay) {
            currentModelDisplay.textContent = this.currentModel;
        }
    }
    
    showToast(message, type = 'info') {
        // 创建提示框
        const toast = document.createElement('div');
        toast.className = `toast toast-${type}`;
        toast.textContent = message;
        
        // 添加样式
        Object.assign(toast.style, {
            position: 'fixed',
            top: '20px',
            right: '20px',
            padding: '12px 20px',
            borderRadius: '8px',
            color: 'white',
            fontSize: '14px',
            fontWeight: '500',
            zIndex: '9999',
            opacity: '0',
            transform: 'translateY(-20px)',
            transition: 'all 0.3s ease'
        });
        
        // 设置背景色
        const colors = {
            success: '#10b981',
            error: '#ef4444',
            info: '#3b82f6'
        };
        toast.style.backgroundColor = colors[type] || colors.info;
        
        document.body.appendChild(toast);
        
        // 显示动画
        setTimeout(() => {
            toast.style.opacity = '1';
            toast.style.transform = 'translateY(0)';
        }, 100);
        
        // 自动隐藏
        setTimeout(() => {
            toast.style.opacity = '0';
            toast.style.transform = 'translateY(-20px)';
            setTimeout(() => {
                if (toast.parentNode) {
                    toast.parentNode.removeChild(toast);
                }
            }, 300);
        }, 3000);
    }
    
    // 个人中心相关方法
    toggleUserDropdown() {
        const dropdown = document.getElementById('userDropdown');
        if (dropdown) {
            dropdown.classList.toggle('show');
        }
    }
    
    closeUserDropdown() {
        const dropdown = document.getElementById('userDropdown');
        if (dropdown) {
            dropdown.classList.remove('show');
        }
    }
    
    downloadApp() {
        // 下载APP功能
        this.showToast('APP下载功能即将上线', 'info');
    }
    
    // ========== 侧边栏缓存管理 ==========
    
    /**
     * 加载缓存的侧边栏数据
     */
    loadCachedData() {
        // 加载角色数据缓存
        const charactersCache = this.getCacheData('characters');
        if (charactersCache) {
            this.allCharacters = charactersCache;
            this.refreshFeaturedCharacters();
            console.log('从缓存加载角色数据:', charactersCache.length, '个角色');
        }
        
        // 加载搜索历史缓存
        const searchHistoryCache = this.getCacheData('searchHistory');
        if (searchHistoryCache) {
            this.searchHistory = searchHistoryCache;
            console.log('从缓存加载搜索历史:', searchHistoryCache.length, '条记录');
        }
    }
    
    /**
     * 预加载侧边栏数据
     */
    async preloadSidebarData() {
        // 如果角色数据已缓存且未过期，跳过加载
        if (this.isCacheValid('characters')) {
            console.log('角色数据缓存有效，跳过预加载');
            return;
        }
        
        // 预加载角色数据
        if (!this.allCharacters || this.allCharacters.length === 0) {
            console.log('预加载角色数据...');
            await this.loadCharacters();
        }
    }
    
    /**
     * 设置缓存数据
     * @param {string} type - 缓存类型
     * @param {any} data - 要缓存的数据
     */
    setCacheData(type, data) {
        const cacheKey = this.cacheKeys[type];
        if (!cacheKey) {
            console.warn('未知的缓存类型:', type);
            return;
        }
        
        const cacheData = {
            data: data,
            timestamp: Date.now(),
            ttl: this.sidebarCache[type].ttl
        };
        
        try {
            localStorage.setItem(cacheKey, JSON.stringify(cacheData));
            this.sidebarCache[type] = cacheData;
            console.log(`缓存${type}数据成功:`, data.length || 0, '条记录');
        } catch (error) {
            console.error(`缓存${type}数据失败:`, error);
        }
    }
    
    /**
     * 获取缓存数据
     * @param {string} type - 缓存类型
     * @returns {any|null} 缓存的数据或null
     */
    getCacheData(type) {
        const cacheKey = this.cacheKeys[type];
        if (!cacheKey) {
            console.warn('未知的缓存类型:', type);
            return null;
        }
        
        try {
            const cached = localStorage.getItem(cacheKey);
            if (!cached) {
                return null;
            }
            
            const cacheData = JSON.parse(cached);
            
            // 检查缓存是否过期
            if (Date.now() - cacheData.timestamp > cacheData.ttl) {
                console.log(`${type}缓存已过期，清除缓存`);
                this.clearCache(type);
                return null;
            }
            
            return cacheData.data;
        } catch (error) {
            console.error(`读取${type}缓存失败:`, error);
            return null;
        }
    }
    
    /**
     * 检查缓存是否有效
     * @param {string} type - 缓存类型
     * @returns {boolean} 缓存是否有效
     */
    isCacheValid(type) {
        const cacheData = this.sidebarCache[type];
        if (!cacheData || !cacheData.data || !cacheData.timestamp) {
            return false;
        }
        
        return Date.now() - cacheData.timestamp < cacheData.ttl;
    }
    
    /**
     * 清除指定类型的缓存
     * @param {string} type - 缓存类型
     */
    clearCache(type) {
        const cacheKey = this.cacheKeys[type];
        if (!cacheKey) {
            console.warn('未知的缓存类型:', type);
            return;
        }
        
        try {
            localStorage.removeItem(cacheKey);
            this.sidebarCache[type] = {
                data: null,
                timestamp: null,
                ttl: this.sidebarCache[type].ttl
            };
            console.log(`清除${type}缓存成功`);
        } catch (error) {
            console.error(`清除${type}缓存失败:`, error);
        }
    }
    
    /**
     * 清除所有侧边栏缓存
     */
    clearAllSidebarCache() {
        Object.keys(this.cacheKeys).forEach(type => {
            this.clearCache(type);
        });
        console.log('清除所有侧边栏缓存成功');
    }
    
    /**
     * 强制刷新指定类型的数据
     * @param {string} type - 数据类型
     */
    async forceRefreshData(type) {
        console.log(`强制刷新${type}数据...`);
        
        // 清除缓存
        this.clearCache(type);
        
        // 重新加载数据
        switch (type) {
            case 'characters':
                await this.loadCharacters();
                break;
            case 'chatHistory':
                await this.loadChatHistory();
                break;
            case 'searchHistory':
                // 搜索历史不需要从后端加载，从本地存储重新读取
                this.searchHistory = JSON.parse(localStorage.getItem('searchHistory') || '[]');
                this.setCacheData('searchHistory', this.searchHistory);
                break;
            default:
                console.warn('未知的数据类型:', type);
        }
    }
    
    // 加载角色对话历史
    async loadCharacterConversation() {
        if (!this.currentCharacter || !this.token) {
            console.log('No character selected or not logged in, showing welcome message');
            this.addWelcomeMessage();
            return;
        }
        
        try {
            const response = await this.fetchWithAuth(`/api/chat/character/${this.currentCharacter.id}/conversation`);
            
            if (response.ok) {
                const messages = await response.json();
                console.log('Loaded conversation history:', messages);
                
                if (messages && messages.length > 0) {
                    // 显示历史消息
                    messages.forEach(msg => {
                        this.addMessage(msg.messageType.toLowerCase(), msg.content, msg.createdAt);
                    });
                    
                    // 设置会话ID（从最后一条消息获取）
                    if (messages.length > 0) {
                        this.currentSession = messages[0].sessionId;
                    }
                } else {
                    // 没有历史对话，显示欢迎消息
                    this.addWelcomeMessage();
                }
            } else {
                console.log('No conversation history found, showing welcome message');
                this.addWelcomeMessage();
            }
        } catch (error) {
            console.error('Error loading conversation history:', error);
            this.addWelcomeMessage();
        }
    }
    
    // 添加对话管理控件
    addConversationControls() {
        const chatActions = document.querySelector('.modern-chat-actions');
        if (!chatActions) return;
        
        // 检查是否已经添加了控件
        if (chatActions.querySelector('.conversation-controls')) return;
        
        const controlsHtml = `
            <div class="conversation-controls">
                <button class="modern-chat-btn" onclick="app.startNewConversation()" title="开始新对话">
                    <i class="bi bi-plus-lg"></i>
                </button>
                <button class="modern-chat-btn" onclick="app.showConversationHistory()" title="查看对话历史">
                    <i class="bi bi-clock-history"></i>
                </button>
            </div>
        `;
        
        // 在关闭按钮之前插入对话管理按钮
        const closeButton = chatActions.querySelector('button[onclick="closeChat()"]');
        if (closeButton) {
            closeButton.insertAdjacentHTML('beforebegin', controlsHtml);
        } else {
            chatActions.insertAdjacentHTML('beforeend', controlsHtml);
        }
    }
    
    // 开始新对话
    async startNewConversation() {
        if (!this.currentCharacter || !this.token) {
            this.showToast('请先登录', 'warning');
            return;
        }
        
        try {
            const response = await this.fetchWithAuth(`/api/chat/character/${this.currentCharacter.id}/new-conversation`, {
                method: 'POST'
            });
            
            if (response.ok) {
                const sessionData = await response.json();
                this.currentSession = sessionData.sessionId;
                
                // 清空聊天记录
                const chatMessages = document.getElementById('chatMessages');
                if (chatMessages) {
                    chatMessages.innerHTML = '';
                }
                
                // 显示欢迎消息
                this.addWelcomeMessage();
                
                this.showToast('已开始新对话', 'success');
            } else {
                this.showToast('开始新对话失败', 'error');
            }
        } catch (error) {
            console.error('Error starting new conversation:', error);
            this.showToast('开始新对话失败', 'error');
        }
    }
    
    // 显示对话历史
    async showConversationHistory() {
        if (!this.currentCharacter || !this.token) {
            this.showToast('请先登录', 'warning');
            return;
        }
        
        try {
            const response = await this.fetchWithAuth(`/api/chat/character/${this.currentCharacter.id}/sessions`);
            
            if (response.ok) {
                const sessions = await response.json();
                this.showConversationHistoryModal(sessions);
            } else {
                this.showToast('获取对话历史失败', 'error');
            }
        } catch (error) {
            console.error('Error loading conversation history:', error);
            this.showToast('获取对话历史失败', 'error');
        }
    }
    
    // 显示对话历史模态框
    showConversationHistoryModal(sessions) {
        // 创建模态框HTML
        const modalHtml = `
            <div class="modal fade" id="conversationHistoryModal" tabindex="-1">
                <div class="modal-dialog modal-lg">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">与 ${this.currentCharacter.name} 的对话历史</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                        </div>
                        <div class="modal-body">
                            <div class="conversation-list">
                                ${sessions.length === 0 ? 
                                    '<p class="text-muted text-center">暂无对话历史</p>' :
                                    sessions.map(session => `
                                        <div class="conversation-item border rounded p-3 mb-2" style="cursor: pointer;" 
                                             onclick="app.loadConversationSession('${session.sessionId}')">
                                            <div class="d-flex justify-content-between align-items-start">
                                                <div>
                                                    <h6 class="mb-1">${session.sessionTitle || '对话'}</h6>
                                                    <small class="text-muted">
                                                        消息数: ${session.messageCount || 0} | 
                                                        最后更新: ${new Date(session.updatedAt).toLocaleString()}
                                                    </small>
                                                </div>
                                                <button class="btn btn-sm btn-outline-danger" 
                                                        onclick="event.stopPropagation(); app.deleteConversationSession('${session.sessionId}')">
                                                    <i class="fas fa-trash"></i>
                                                </button>
                                            </div>
                                        </div>
                                    `).join('')
                                }
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        // 移除已存在的模态框
        const existingModal = document.getElementById('conversationHistoryModal');
        if (existingModal) {
            existingModal.remove();
        }
        
        // 添加新模态框
        document.body.insertAdjacentHTML('beforeend', modalHtml);
        
        // 显示模态框
        const modal = new bootstrap.Modal(document.getElementById('conversationHistoryModal'));
        modal.show();
    }
    
    // 加载指定会话
    async loadConversationSession(sessionId) {
        try {
            const response = await this.fetchWithAuth(`/api/chat/history/${sessionId}`);
            
            if (response.ok) {
                const messages = await response.json();
                
                // 设置当前会话
                this.currentSession = sessionId;
                
                // 清空并重新加载消息
                const chatMessages = document.getElementById('chatMessages');
                if (chatMessages) {
                    chatMessages.innerHTML = '';
                }
                
                // 显示消息
                messages.forEach(msg => {
                    this.addMessage(msg.messageType.toLowerCase(), msg.content, msg.createdAt);
                });
                
                // 关闭模态框
                const modal = bootstrap.Modal.getInstance(document.getElementById('conversationHistoryModal'));
                if (modal) {
                    modal.hide();
                }
                
                this.showToast('已加载对话', 'success');
            } else {
                this.showToast('加载对话失败', 'error');
            }
        } catch (error) {
            console.error('Error loading conversation session:', error);
            this.showToast('加载对话失败', 'error');
        }
    }
    
    // 删除对话会话
    async deleteConversationSession(sessionId) {
        if (!confirm('确定要删除这个对话吗？')) {
            return;
        }
        
        try {
            const response = await this.fetchWithAuth(`/api/chat/sessions/${sessionId}`, {
                method: 'DELETE'
            });
            
            if (response.ok) {
                this.showToast('对话已删除', 'success');
                // 重新加载对话历史
                this.showConversationHistory();
            } else {
                this.showToast('删除对话失败', 'error');
            }
        } catch (error) {
            console.error('Error deleting conversation session:', error);
            this.showToast('删除对话失败', 'error');
        }
    }
}

// 全局变量和函数
let app;

// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', () => {
    app = new RelieveAnxietyApp();
});

// 全局函数（供HTML调用）
function searchCharacters() {
    app.searchCharacters();
}

function closeChat() {
    app.closeChat();
}

function sendMessage() {
    app.sendMessage();
}

function toggleVoiceRecording() {
    app.toggleVoiceRecording();
}

function handleKeyPress(event) {
    if (event.key === 'Enter') {
        app.sendMessage();
    }
}

// 认证相关的全局函数
function showLoginModal() {
    const modal = new bootstrap.Modal(document.getElementById('loginModal'));
    modal.show();
}

function showRegisterModal() {
    const modal = new bootstrap.Modal(document.getElementById('registerModal'));
    modal.show();
}

function showChatHistory() {
    app.loadChatHistory();
    const modal = new bootstrap.Modal(document.getElementById('chatHistoryModal'));
    modal.show();
}

function logout() {
    app.logout();
}

// 语音通话相关全局函数
function startVoiceCall() {
    app.startVoiceCall();
}

function toggleMicrophone() {
    app.toggleMicrophone();
}

function endVoiceCall() {
    app.endVoiceCall();
}

function toggleTextDisplay() {
    app.toggleTextDisplay();
}

function copyAiResponse() {
    app.copyAiResponse();
}

function interruptAiResponse() {
    app.interruptAiResponse();
}

// 换一批角色
function refreshCharacters() {
    app.refreshFeaturedCharacters();
    app.refreshCharacters();
}

// 侧边栏相关函数
function toggleSidebar() {
    app.toggleSidebar();
}

function closeSidebar() {
    app.closeSidebar();
}

function toggleAllCharacters() {
    app.toggleAllCharacters();
}

// 模型下拉菜单相关函数
function toggleModelDropdown() {
    const dropdown = document.getElementById('modelDropdown');
    if (dropdown) {
        dropdown.classList.toggle('show');
    }
}

function closeModelDropdown() {
    const dropdown = document.getElementById('modelDropdown');
    if (dropdown) {
        dropdown.classList.remove('show');
    }
}

// 点击外部关闭下拉菜单
document.addEventListener('click', function(event) {
    const modelSelector = document.querySelector('.model-selector');
    const modelDropdown = document.getElementById('modelDropdown');
    
    if (modelSelector && modelDropdown && 
        !modelSelector.contains(event.target) && 
        !modelDropdown.contains(event.target)) {
        closeModelDropdown();
    }
    
    // 关闭用户下拉菜单
    const userAvatarContainer = document.querySelector('.user-avatar-container');
    const userDropdown = document.getElementById('userDropdown');
    
    if (userAvatarContainer && userDropdown && 
        !userAvatarContainer.contains(event.target) && 
        !userDropdown.contains(event.target)) {
        app.closeUserDropdown();
    }
});

// 个人中心相关函数
function toggleUserDropdown() {
    app.toggleUserDropdown();
}

function downloadApp() {
    app.downloadApp();
}

// 搜索相关函数
function clearSearch() {
    app.clearSearch();
}


function selectCharacter(characterId) {
    app.selectCharacter(characterId);
}

function refreshLocalCache() {
    app.refreshLocalCache();
}

// 对话管理相关函数
function startNewConversation() {
    app.startNewConversation();
}

function showConversationHistory() {
    app.showConversationHistory();
}

